将 char * 转换为 char ** 时出现分段错误
Segmentation fault when converting char * to char **
我正在尝试将一个句子 (char *) 拆分为一个单词数组 (char **)。问题是我的函数有时不会 return 有效的 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] != '[=10=]' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '[=10=]';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '[=10=]';
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] != '[=13=]' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '[=13=]';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '[=13=]';
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]);
}
如果您在学习编程方面需要帮助,可以试试静态分析器。这是一个执行代码审查并发现可疑代码片段的程序。静态分析器无法取代队友执行的代码审查。但是,分析器补充代码审查并帮助在最早阶段发现许多错误。
让我们run the online version of the PVS-Studio analyzer for the code sample attached to the question. The first interesting and important warning is the following warning: V1031不声明malloc
函数。将数据传入或传出此函数可能会受到影响。
没有声明malloc
函数,程序运行的方式很奇怪。按照C语言,如果一个函数没有被声明,它就是returnsint
。但实际上,它是一个指针。你可以找出为什么这是危险的 here。让我们通过添加 #include <stdlib.h>
.
来解决这个问题
Now 分析器发出另一个警告——我们遇到了一个更严重的问题:
43:1: note: V773 'buffer' 指针在没有释放内存的情况下被赋值了两次。可能存在内存泄漏。
问题出在以下代码片段中:
char *buffer = malloc(sizeof(char) * 100);
buffer = "hello world !\n";
....
free (buffer);
指针值被覆盖。要将字符串复制到缓冲区,程序员应该使用特殊函数,例如 strcpy
。让我们解决这个问题。
这是 fixed code。
#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] != '[=11=]' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '[=11=]';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '[=11=]';
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]);
}
我不能说这个代码是完美和安全的,但是它运行了。因此,使用静态分析器查找错误,可以改进您的学习过程。
我正在尝试将一个句子 (char *) 拆分为一个单词数组 (char **)。问题是我的函数有时不会 return 有效的 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] != '[=10=]' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '[=10=]';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '[=10=]';
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] != '[=13=]' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '[=13=]';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '[=13=]';
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]);
}
如果您在学习编程方面需要帮助,可以试试静态分析器。这是一个执行代码审查并发现可疑代码片段的程序。静态分析器无法取代队友执行的代码审查。但是,分析器补充代码审查并帮助在最早阶段发现许多错误。
让我们run the online version of the PVS-Studio analyzer for the code sample attached to the question. The first interesting and important warning is the following warning: V1031不声明malloc
函数。将数据传入或传出此函数可能会受到影响。
没有声明malloc
函数,程序运行的方式很奇怪。按照C语言,如果一个函数没有被声明,它就是returnsint
。但实际上,它是一个指针。你可以找出为什么这是危险的 here。让我们通过添加 #include <stdlib.h>
.
Now 分析器发出另一个警告——我们遇到了一个更严重的问题: 43:1: note: V773 'buffer' 指针在没有释放内存的情况下被赋值了两次。可能存在内存泄漏。
问题出在以下代码片段中:
char *buffer = malloc(sizeof(char) * 100);
buffer = "hello world !\n";
....
free (buffer);
指针值被覆盖。要将字符串复制到缓冲区,程序员应该使用特殊函数,例如 strcpy
。让我们解决这个问题。
这是 fixed code。
#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] != '[=11=]' && buffer[i] != '\n'; i++, l++) {
if (buffer[i] == delimiter) {
words[word_count][l] = '[=11=]';
word_count++;
l = -1;
}
else
words[word_count][l] = buffer[i];
}
words[word_count][l] = '[=11=]';
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]);
}
我不能说这个代码是完美和安全的,但是它运行了。因此,使用静态分析器查找错误,可以改进您的学习过程。