我很抱歉这个模糊的标题,但我很难弄清楚如何描述这个问题。我正在尝试将数据添加到数组中,不管怎么说,尽管我明确指出,但它都会被写入索引0。我创建了一个最小的样本。
命令行参数为-u rwx -g rw -o r
:
指数0,1和2都以"100"
结尾。如果您使用printf()
检查各种case
语句中的值,您会发现,例如,当case 'g':
运行时,bins[1] == "110"
和bins[0] == "110"
。当case 'o':
运行时,所有三个索引都将保留值"100"
。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void processPerms(char *targets, char **perms, char **bins, const size_t arrSize) {
for(int i = 0; i < arrSize; i++) {
//This string will be modified
//so that the right bits will
//be set.
char binDig[] = "000";
//We decide which, if any, bit
//to set based upon the current
//letter being considered.
for(int k = 0; k < strlen(perms[i]); k++) {
switch(perms[i][k]) {
case 'r':
binDig[0] = '1';
break;
case 'w':
binDig[1] = '1';
break;
case 'x':
binDig[2] = '1';
break;
}
}
//Here, we check the target
//whose index corresponds to
//the index of the permissions
//string we just accessed.
//They will always be in
//an order where the related
//target and perm str are in
//the same array position.
switch(targets[i]) {
case 'u':
bins[0] = binDig;
//bins[0] == "111"
break;
case 'g':
bins[1] = binDig;
//bins[0] == "110"
break;
case 'o':
bins[2] = binDig;
//bins[0] == "100" && bins[1] == "100"
break;
}
}
}
int main(int argc, char *argv[]) {
const size_t arrSize = (argc-1)/2;
char *targets = (char*)calloc(arrSize, sizeof(char));
char **perms = (char**)calloc(arrSize, sizeof(char*));
//Copying just the letters
//of the args into these
//arrays.
for(int i = 0; i < arrSize; i++) {
targets[i] = argv[i+(i+1)][1];
}
for(int i = 0; i < arrSize; i++) {
perms[i] = argv[i*2+2];
}
//This array should hold three
//strings which shall be binary
//representations of the
//permissions
char **bins = (char**)calloc(3, sizeof(char*));
processPerms(targets, perms, bins, arrSize);
return 0;
}
答案 0 :(得分:1)
bins[2] = binDig;
这将使您指向具有自动存储持续时间的变量。当您从函数返回时,这是一个未定义行为的网关。变量的生命周期结束,就像在这种情况下一样,访问它是UB。(取消引用变量超出其生命周期的指针是Undefine d行为)。
一个简单的解决方案是使用(这是POSIX标准的一部分,但它很常见)(如果你没有这个,你可以分配内存并将数据的内容复制到它{{1} })。
binDig
(对bins[2] = strdup(binDig);
和bins[0]
进行相同的更改。
如上所述进行此更改会使bins[1]
的预期行为等于“111”,依此类推。唯一的一点是,你需要释放动态分配的内存(包括bins[0]
返回的内存
当你完成它的时候)。同样,不要强制转换strdup
,malloc
等的返回值(因为calloc
到void*
是隐式转换)。并检查char*
的返回值。
答案 1 :(得分:1)
binDig
数组的生命周期受外部for
周期的一次迭代的限制。这个binDig
数组在每次迭代结束时被销毁,并在下一次迭代开始时重新创建。
这意味着当迭代结束时,在外循环的每次迭代期间执行的所有操作都将丢失。您在该迭代期间分配的bins[]
的值开始指向内存中不再存在的某个不确定位置。任何通过相应bins[]
条目访问数据的尝试都会导致未定义的行为。
在现实生活中,循环的每次迭代通常会在内存中完全相同的位置重新创建binDig
,这会产生所有bins[]
指针保持有效但指向相同值的错觉。但这只是一种幻觉。此时行为已经未定义。
当外部循环结束时,binDig
数组将永远消失,并且所有bins[]
指针都变得无可救药地无效。但那只是最后一根稻草。你的节目在那之前就已经很好了。