将 char * 转换为 char ** 时出现分段错误

问题描述 投票:0回答:1
我正在尝试将句子(char *)拆分为单词数组(char **)。问题是我的函数有时不会返回有效的字符 **。

char **get_words(char *buffer, char delimiter) { char **words = malloc(sizeof(char *) * 4096); for (int i = 0; i < 4096; i++) words[i] = malloc(sizeof(char) * 4096); int word_count = 0; int l = 0; for (int i = 0; buffer[i] != '\0' && buffer[i] != '\n'; i++, l++) { if (buffer[i] == delimiter) { words[word_count][l] = '\0'; word_count++; l = -1; } else words[word_count][l] = buffer[i]; } words[word_count][l] = '\0'; return (words); }
我首先这样使用它:

char *buffer = malloc(sizeof(char) * 50); buffer = "/login test\n"; char **words = get_words(buffer, ' '); printf("Words[0] = %s", words[0]);
而且效果很好。

但是,当我以同样的方式这样做时:

char **reply = get_words("502 Command doesn't exist.\n", ' ')
我什至无法在没有分段错误的情况下打印回复[0][0](见下文)。
此外,我尝试使用 valgrind 进行调试,但是当我使用它时,程序不会崩溃并且一切正常,所以我找不到问题所在。

printf("Reply[0][0] = %d\n", reply[0][0]);


printf("Reply[0][0] = %c\n", reply[0][0]);


编辑: 这是一个可重现的示例。

#include <unistd.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <assert.h> char **get_words(char *buffer, char delimiter) { printf("buffer = %s\n", buffer); char **words = malloc(sizeof(char *) * 100); if (words == NULL) { printf("Malloc Error\n"); exit(84); } for (int i = 0; i < 100; i++) { words[i] = malloc(sizeof(char) * 100); if (words[i] == NULL) { printf("Malloc Error\n"); exit(84); } } int word_count = 0; int l = 0; for (int i = 0; buffer[i] != '\0' && buffer[i] != '\n'; i++, l++) { if (buffer[i] == delimiter) { words[word_count][l] = '\0'; word_count++; l = -1; } else words[word_count][l] = buffer[i]; } words[word_count][l] = '\0'; return (words); } int main() { char *buffer = malloc(sizeof(char) * 100); buffer = "hello world !\n"; char **words = get_words(buffer, ' '); printf("words[0]= %s\n", words[0]); free (buffer); char **reply = get_words("Second call\n", ' '); printf("reply[0] = %s\n", reply[0]); }
    
c valgrind
1个回答
5
投票
使用静态分析器,第一个有趣且重要的警告是以下警告:未声明

malloc

 函数。将此函数传入或传出的数据可能会受到影响。

如果没有声明

malloc

 函数,程序就会以一种奇怪的方式运行。根据C语言,如果函数没有声明,则返回
int
。但实际上,它是一个指针。让我们通过添加 
#include <stdlib.h>
 来解决这个问题。

现在分析器发出另一个警告——我们遇到了一个更严重的问题: 43:1:注意:V773 “缓冲区”指针被赋值两次而没有释放内存。可能存在内存泄漏。

问题出在以下代码片段中:

char *buffer = malloc(sizeof(char) * 100); buffer = "hello world !\n"; .... free (buffer);
指针值被覆盖。要将字符串复制到缓冲区,程序员应该使用特殊函数,例如 

strcpy

。让我们解决这个问题。

这是

固定代码

#include <unistd.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <assert.h> #include <stdlib.h> char **get_words(char *buffer, char delimiter) { printf("buffer = %s\n", buffer); char **words = malloc(sizeof(char *) * 100); if (words == NULL) { printf("Malloc Error\n"); exit(84); } for (int i = 0; i < 100; i++) { words[i] = malloc(sizeof(char) * 100); if (words[i] == NULL) { printf("Malloc Error\n"); exit(84); } } int word_count = 0; int l = 0; for (int i = 0; buffer[i] != '\0' && buffer[i] != '\n'; i++, l++) { if (buffer[i] == delimiter) { words[word_count][l] = '\0'; word_count++; l = -1; } else words[word_count][l] = buffer[i]; } words[word_count][l] = '\0'; return (words); } int main() { char *buffer = malloc(sizeof(char) * 100); if (buffer == NULL) exit(84); strcpy(buffer, "hello world !\n"); char **words = get_words(buffer, ' '); printf("words[0]= %s\n", words[0]); free (buffer); char **reply = get_words("Second call\n", ' '); printf("reply[0] = %s\n", reply[0]); }
我不能说这段代码是完美和安全的,但它可以运行。因此,使用静态分析器来查找错误,可以改进您的学习过程。

© www.soinside.com 2019 - 2024. All rights reserved.