为何memset初始化字符串数组触发段错误,calloc却正常?
问题原因分析
首先明确两个核心点:
char *string_array[26];是栈上的指针数组,它本身在栈上,但数组里的每个char*元素只是指针,初始值是随机的垃圾地址,并没有指向任何合法的可写内存。memset的作用是填充已分配的内存,它不负责分配内存。
为什么第一段代码会触发段错误?
你直接调用memset(string_array[x], 0, 3 + x)时,string_array[x]是未初始化的野指针,指向的是完全随机的内存区域:
- 可能指向只读内存(比如代码段),写入会触发权限错误;
- 可能指向栈外的无效地址,操作系统会直接终止进程;
- 甚至可能指向其他正在使用的内存,破坏数据后导致未知崩溃。
这种情况下,memset去写入一块不属于你的内存,必然触发段错误。
为什么calloc版本没问题?
calloc(3 + x, sizeof(char))会从堆上分配一块大小为3+x的内存,并且返回这块内存的合法可写地址,然后你把这个地址赋值给string_array[x]。此时string_array[x]指向的是你拥有权限的堆内存,后续操作自然不会出错。
如何实现「不放在堆上」的需求?
如果想把字符串内存也放在栈上,可以用栈上的二维数组:
// 栈上分配26个字符串,每个字符串的最大长度是3+25=28(x最大是25) char string_array[26][28]; for (int x = 0; x < 26; x++) { memset(string_array[x], 0, 3 + x); }
或者用变长数组(注意C99及以上支持,且栈空间有限,避免过大导致栈溢出):
int max_len = 3 + 25; char string_array[26][max_len]; for (int x = 0; x < 26; x++) { memset(string_array[x], 0, 3 + x); }
也可以用alloca在栈上动态分配每个字符串的内存(同样要注意栈容量限制):
char *string_array[26]; for (int x = 0; x < 26; x++) { string_array[x] = alloca(3 + x); memset(string_array[x], 0, 3 + x); }
内容的提问来源于stack exchange,提问作者Connor
相关产品推荐
相关产品推荐

