c - 当我在 C 中 malloc 另一个字符串时,字符串发生了变化
问题描述
我目前正在制作外壳。我想将一个简单的字符串分成一个二维数组。起初它工作得很好,但现在我有一个奇怪的问题:我的简单字符串“str”在我 malloc 任何东西后发生了变化。例如,如果我创建一个新数组,例如
char *tmp = malloc(sizeof(char) * 15));
然后 my str
, which was"ls -l"
将变成" OO"
or " A"
。
我已经尝试改变 malloc 的大小,但它并没有解决问题,尽管它确实做出了str
不同的改变。她是我的代码:
char **mem_alloc_2d_array(int nb_rows, int nb_cols) {
char **map = malloc(nb_rows * sizeof(*map + 1));
for (int i = 0; i < nb_rows; i++) {
map[i] = malloc(nb_cols * sizeof(**map + 1));
}
return map;
}
int what_is_x(char const *str) {
int x = 2;
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == ' ')
x++;
}
return x;
}
char **try_this(char const *str) {
int size = my_strlen(str);
int x = what_is_x(str);
char **words = mem_alloc_2d_array(x, size);
return words;
}
char **my_str_to_wordtab(char *str) {
int j = 0;
int i = 0;
char **words = try_this(str);
if (str[0] == '\n' || str[0] == '\r')
words[0] = NULL;
for (; str[i] == ' ' || str[i] == '\t'; i++);
for (int x = 0; str[i] != '\n'; i++, x++) {
if (str[i] == ' ' || str[i] == '\t') {
words[j][x] = '\0';
j++;
x = 0;
while (str[i] == ' ' || str[i] == '\t')
i++;
}
words[j][x] = str[i];
}
j++;
words[j] = (char *)0;
return words;
}
我期望的是,在函数try_this()
中,如果我str
的东西很大,"ls -l Makefile"
那么两个my_putstr(str)
调用都会打印同样的东西,但它们不会。
解决方案
关于对函数的调用,尚不清楚您在谈论什么my_putstr(str)
,因为该函数和对它的任何调用都没有出现在您提供的代码中。不过,我可以肯定地说,您的内存分配代码是有问题的,并且至少部分不正确。考虑一下:
char **map = malloc(nb_rows * sizeof(*map + 1));
. 那里到底+ 1
有什么意义?请注意,*map
有类型char *
,因此也有*map + 1
。sizeof
运算符根据其操作数的类型计算结果,因此您的sizeof
表达式计算的值与sizeof(*map)
. 我猜你可能想要
char **map = malloc((nb_rows + 1) * sizeof(*map));
nb_rows + 1
,它为指针保留空间。
同样,这...
map[i] = malloc(nb_cols * sizeof(**map + 1));
...没有做你可能想要的。要为每个字符串的终止符保留空间,最好写成
map[i] = malloc((nb_cols + 1) * sizeof(**map));
. 但是由于这段代码是特定于字符串的,并且根据定义char
,a 的大小是 1 ,所以我自己实际上会这样写:
map[i] = malloc(nb_cols + 1);
您没有为数据保留足够的空间,看到内存损坏也就不足为奇了。
还要注意,检查内存分配失败(在这种情况下malloc()
返回一个空指针)并在它发生时适当地处理它对于健壮的代码是必不可少的。请养成将其作为例行公事的习惯,尽管不这样做可能不会导致您询问的特定问题。
推荐阅读
- c++ - C++20:自动生成的运算符在派生类中不可引用?
- git - 更新我的 Homebrew 时返回错误
- google-apps-script - 知道插件是域安装的还是单独的
- apache-zookeeper - “bin/zkServer.sh start”和“bin/zookeeper-server-start.sh config/zookeeper.properties”的区别
- node.js - 刮大篮子产品失败
- mongodb - Mongodb $lookup 检索菜单和子菜单作为子文档数组
- inno-setup - 防止自动从安装到完成页面进行,并允许返回到安装页面查看 Inno Setup 中的结果
- javascript - 如何以编程方式在 select2 多选下拉列表中添加其他选择而不会丢失现有的选定项目
- vue.js - Vue分页-如何使用?
- python - django 中的 socket.io-stream(通道)