c - 对 malloc 字符串的赋值表现得很奇怪

标签 c

这是代码,是C代码。请解释“string”的返回值

    char * p = (char*) malloc(sizeof(char) * 100);
    p = "hello";   
    *(p+1) = '1';
    printf("%s", p);
    free(p);

最佳答案

请注意,p = "hello"; 不会复制任何字符串,而只是将指针 p 设置为该地址的地址 6 字节文字字符串 "hello"。要复制字符串,请使用 strncpystrcpy (读取 strncpy(3) ...),但要害怕 buffer overflows

所以你会的

 char * p = malloc(100);

分配一个能够容纳100字节的内存区域。让我们假设 malloc 成功(读取 malloc(3) ...)并返回地址 0x123456(通常,该具体地址在一次运行到下一次运行之间无法重现,例如由于 ASLR )。

然后你分配了 p = "hello"; 所以你忘记了地址 0x123456 (你现在有一个 memory leak ),然后你输入了 p 地址6 字节文字字符串 "hello" (假设它是 0x2468a)。

稍后机器执行 *(p+1) = '1'; 的代码,因此您尝试替换其中的 e 字符(位于地址 0x2468b) 1 的文字 "hello"。你会得到一个 segmentation violation (或其他一些 undefined behavior ),因为该文字字符串位于常量只读内存中(例如可执行文件的 text segment ,至少在 Linux 上)。

更好的代码可能是:

 #define MY_BUFFER_LEN 100
 char *p = malloc(MY_BUFFER_LEN);
 if (!p) { perror("malloc for p"); exit(EXIT_FAILURE); };
 strncpy(p, "hello", MY_BUFFER_LEN); /// you could do strcpy(p, "hello")
 *(p+1) = '1';
 printf("%s", p);
 free(p);

如果你幸运的话(没有内存故障),很久会输出h1llo(只有当stdout刷新时才会发生输出因为它是 buffered ,例如通过稍后调用 fflush )。所以别忘了打电话

 fflush(NULL);

在上一个代码块之后。阅读 perror(3)fflush(3)

一般建议是阅读您正在使用的每个函数的 documentation(甚至 printf(3) ...)。

关于 printf 及相关函数,由于 stdout 通常是 line buffered ,在实践中我强烈建议以 \n 结束每个格式控制字符串-例如。 printf("%s\n", p); 在您的代码中;当您不这样做时(在某些情况下您不想...)请三思而后行,也许可以评论您的代码。

不要忘记使用所有警告和调试信息进行编译(例如 gcc -Wall -Wextra -g),然后学习如何使用调试器(例如 gdb)

关于c - 对 malloc 字符串的赋值表现得很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28752828/

相关文章:

用字符串数组替换字符串的 C 程序

c++ - 关于多线程程序的查询

c++ - 为什么我的 C/C++ header 解析器不工作?

c - 如何在 C 中声明指向结构数组的指针

c - 在 C 中传递数组、指向 int 的指针

c - mmap on/proc/pid/mem

当前出现段错误 : 11 and I am unsure why?

c - 从文件中添加数字的示例 C 程序

c - 不明白这段代码是如何缩放bmp图像的

c++ - 解释 Valgrind 的 trace-malloc 输出