2010-05-12 37 views
5

gcc 4.4.3 c89堆栈转储访问malloc字符数组

我有以下源代码。在printf上获取堆栈转储。

char **devices; 
devices = malloc(10 * sizeof(char*)); 

strcpy(devices[0], "smxxxx1"); 

printf("[ %s ]\n", devices[0]); /* Stack dump trying to print */ 

我想这应该创建一个像这样的char数组。

devices[0] 
devices[1] 
devices[2] 
devices[4] 
etc 

而且每个元素都可以存储我的字符串。

===

for(i = 0; i < 10; i++) 
{ 
    devices[i] = malloc(strlen("smxxxx1")+1); 
} 
+1

对于引发几个几乎相同的答案的问题的荣誉。 – sum1stolemyname 2010-05-12 09:01:22

+0

堆栈转储或核心转储? – 2010-05-12 11:17:19

+0

@Matt Curtis:我似乎记得gcc生成的程序为win32生成堆栈转储到他们在出现某种类型的错误时运行的dos框。它似乎没有在我当前的设置上做到这一点,虽然(明戈,Vista,x86-32)。 – nategoose 2010-05-12 19:13:15

回答

5

您已经为指针数组分配了内存。您需要为每个元素分配内存以存储字符串

例如,

#define NUM_ELEMENTS 10 
char **devices; 
devices = malloc(NUM_ELEMENTS * sizeof(char*)); 

for (int i = 0; i < NUM_ELEMENTS; i++) 
{ 
    devices[i] = malloc(length_of string + 1); 
} 
+0

您可以引入NUM_ELELENTS,并在malloc()调用中仍使用10。 – sharptooth 2010-05-12 12:06:13

1

已为指针(设备)分配空间,但非常感谢您的任何建议,

==加修正没有为你要存储字符串分配的空间。

2

您只分配了一个指向数组的指针数组。 你必须为每个你打算存储字符串分配内存:存储10字符指针

char **devices; 
devices = malloc(10 * sizeof(char*)); 

//Added this line: 

devices[0] = (char*)malloc(strlen("smxxxx1")+1); 
strcpy(devices[0], "smxxxx1\0"); 

printf("[ %s ]\n", devices[0]); /* Stack dump trying to print */ 
+2

你的字符串确实不需要明确包含'\ 0',它们已经以NULL结尾 – Hasturkun 2010-05-12 09:02:20

+0

只是想知道作为一个额外的预防措施。实际的char数组应该是NULL终止的。我有10个元素。但是,第10个应该是NULL。这是万一你正在循环显示,你想停在NULL?只是一个想法谢谢。 – ant2009 2010-05-12 09:10:38

+1

@robUK:在数组末尾使用NULL作为标记值有时是常见操作(例如'argv')。这取决于实际情况;有时可能没有适合的值作为标记(如果NULL是数组中的合法元素,如果不处理指针数组会怎么样?)。 – jamesdlin 2010-05-12 09:55:15

3

您已分配的内存。要在这些内存位置存储一个字符串,你必须为它们分配内存。基本上你需要像每个指针device[0] = malloc(stringLen + 1);

4

设备[0]是char *,但您尚未分配任何存储空间。而是执行此操作:

char **devices; 
devices = malloc(10 * sizeof(char*)); 

devices[0] = strdup("smxxxx1"); 

printf("[ %s ]\n", devices[0]); 

最终,你必须释放被strdup()分配的内存:

free(devices[0]); 
0

设备是一个指针数组。您正在复制字符串“smxxxx1”而不是该数组,当它看起来像要设置元素0指向该字符串时。

代替的strcpy()的尝试:

devices[0] = "smxxxx1" 

devices[0] = strdup("smxxxx1") 

编辑:

在32位的系统,装置[0]是由四个字节。这四个字节将被字符串“smxxxx1”的前四个字符的字节值覆盖。在ascii这些是0x73,0x6D,0x78,0x78。假设地址为little-endian,则最终将包含指向地址0x78786D73的指针的设备[0]。这个地址在这个过程中几乎肯定不会有效。当调用printf()试图取消引用这个无效指针时,操作系统会触发分段错误并转储核心。

问题在于,OP在初始化时错误地将设备变量视为字符串(char数组)。它实际上是一个指针到char的数组,printf()正在解释它。

+0

如果OP的数组是指向const的指针,我会赞成这一点。 – 2010-05-12 11:16:17

+0

稳定性不相关。它是一种语言概念。堆栈转储由操作系统触发。 – 2010-05-12 11:47:13

+0

确定const是一个语言概念,但我宁愿编译器阻止我通过指向const的指针写入,而不是在运行时获取内核陷阱。 – 2010-05-12 20:31:33