为何C语言中动态分配char数组使用strcat会触发段错误?
动态分配char数组与栈char数组使用strcat的行为差异及段错误原因
错误代码的核心问题
你的第一段代码触发段错误,根本原因不是缺少终止空字符,而是指针指向了只读的字符串常量区,且丢失了动态分配的堆内存:
- 执行
char *destination = malloc(30 * sizeof(char));时,destination确实指向了堆上一块30字节的可写内存。 - 但紧接着
destination = "Hello, ";这行代码,直接把destination的指针值替换成了字符串字面量"Hello, "在字符串常量区的地址——原来malloc分配的堆内存从此无法访问,造成内存泄漏。 - 同理,
source = "world!"也让source指向了字符串常量区的只读内存。 strcat(destination, source)试图往只读的字符串常量内存中写入拼接后的内容,而操作系统会保护只读内存不被修改,因此直接触发段错误。
正确代码的工作逻辑
第二段代码能正常运行,是因为栈数组的初始化逻辑完全不同:
char destination[30] = "Hello, ";是在栈上分配了30字节的可写数组内存,并把字符串字面量"Hello, "的内容(包括自带的终止\0)拷贝到了这块数组内存中。strcat(destination, source)是往栈上的可写内存里追加内容,拼接后的总长度("Hello, world!"共13字节)远小于数组的30字节容量,因此不会越界,也没有权限问题。
你的核心误区
你混淆了指针赋值和字符串拷贝:
- 给
char*类型的指针直接赋值字符串字面量(destination = "Hello, ";),不是把字符串内容复制到指针原本指向的内存,而是直接改变指针的指向,让它指向只读的字符串常量区。 - 栈数组的初始化(
char arr[N] = "str";)则是把字符串内容拷贝到数组的可写内存中,这才是真正的"把字符串放到数组里"的操作。
正确使用动态内存的写法
如果要基于动态分配的内存实现字符串拼接,需要用strcpy/strncpy把字符串内容拷贝到堆内存中,而不是直接赋值指针:
char *destination = malloc(30 * sizeof(char)); strcpy(destination, "Hello, "); // 将字符串拷贝到堆内存 char *source = malloc(30 * sizeof(char)); strcpy(source, "world!"); strcat(destination, source); // 使用完记得释放内存,避免泄漏 free(destination); free(source);
内容的提问来源于stack exchange,提问作者Lemury
相关产品推荐
相关产品推荐

