C语言指针数组malloc与strcpy代码内存安全及分配问题咨询
问题1:第一段代码是否存在内存泄漏?valgrind -s无输出是否代表无内存问题
- 这段代码不存在内存泄漏:你对
tokens[0]申请的动态内存已经通过free(tokens[0])完成了释放,剩余两个指针tokens[1]、tokens[2]没有申请过堆内存,不存在未释放的动态内存。 - valgrind -s运行无输出不能完全代表代码没有内存问题:
首先当前代码本身存在非泄漏类的隐患:你引入的
<malloc.h>不是C标准库的标准头文件,标准动态内存分配的头文件是<stdlib.h>,部分编译器可能不支持<malloc.h>导致编译失败。其次全局数组tokens的tokens[1]、tokens[2]未初始化,如果后续代码误访问会触发野指针问题,只是当前代码没有用到这两个指针,valgrind不会触发报错。
除此之外valgrind只能检测运行时实际执行到的路径的内存问题,如果代码存在未执行路径的内存错误、非内存访问类的逻辑错误,valgrind也不会给出提示。
问题2:如何一次性给tokens数组的三个指针分配内存
你原来的写法错误原因是:把多个字符串所需的长度求和后只赋值给了tokens[0],tokens[1]、tokens[2]仍然没有指向有效的内存地址,所以无法正常运行。
正确的实现逻辑是:先计算三个字符串所需的总内存大小,一次性申请一块连续的堆内存,再手动给三个指针分别指向这块内存中对应的偏移位置即可,示例代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> char *tokens[3]; int main() { // 预定义要存储的三个字符串 const char *str1 = "<html>"; const char *str2 = "<title>"; const char *str3 = "<body>"; // 计算总内存需求:每个字符串长度+1(存储结束符'\0')的总和 size_t total_size = (strlen(str1) + 1) + (strlen(str2) + 1) + (strlen(str3) + 1); // 一次性申请总内存,首地址赋值给第一个指针 tokens[0] = malloc(total_size); if (tokens[0] == NULL) { perror("内存申请失败"); return 1; } // 给剩余两个指针分配对应偏移位置 tokens[1] = tokens[0] + strlen(str1) + 1; tokens[2] = tokens[1] + strlen(str2) + 1; // 拷贝字符串到对应位置 strcpy(tokens[0], str1); strcpy(tokens[1], str2); strcpy(tokens[2], str3); // 测试输出 printf("%s\n%s\n%s\n", tokens[0], tokens[1], tokens[2]); // 释放时只需释放首地址即可,不需要逐个释放三个指针 free(tokens[0]); return 0; }
这种分配方式的优势是减少内存碎片,同时避免多次free出现漏释放的问题,注意如果后续需要修改某个指针对应的字符串长度,不能超过预分配的对应位置的内存大小,否则会出现内存越界。
内容的提问来源于stack exchange,提问作者user786
相关产品推荐
相关产品推荐

