首先,对不起标题。我真的不太确定如何表达它。
在 C 中,我有一个 2D 字符串数组,声明和分配如下:
char ** args = malloc(50*(num_args+1));
for (int i = 0; i < num_args+1; i++){
args[i] = malloc(50);
我在一种“基本的 shell”类型程序中使用它,模仿 bash 的一些特性,因此是 num_args 变量。
在多台机器上编译运行,args[4]处的地址总是越界。这是相关的 gdb 输出:
(gdb) print args[0]
$2 = 0x609140 "gcc"
(gdb) print args[1]
$3 = 0x609180 ""
(gdb) print args[2]
$4 = 0x6091c0 ""
(gdb) print args[3]
$5 = 0x609200 ""
(gdb) print args[4]
$6 = 0x636367 <Address 0x636367 out of bounds>
(gdb) print args[5]
$7 = 0x609280 ""
如您所见,args[4] 之前和之后的地址都是有效的。这个地址怎么会越界?
使用此代码的整个函数在这里和下面:
void parse(const char * command){
// first parse built-ins (ie, not a call to the OS)
if (strcmp(command, "history") == 0){
show_history();
return;
}
if (strcmp(command, "exit") == 0){
exit(0);
}
hist_add(command);
// copy 'command' into arg_string, while ignoring any possible comments
char * arg_str;
int num_args = 1;
arg_str = malloc(strlen(command));
for (int i = 0; i < strlen(command); i++){
if (command[i] == '#' || command[i] == '\n') break;
if (command[i] == ' ') num_args++;
arg_str[i] = command[i];
}
// split arg_str into a string array where each string is an argument
// to the command
char ** args = malloc(num_args+1);
for (int i = 0; i < num_args+1; i++){
args[i] = malloc(50);
}
int tokens = 0;
const char token = ' ';
char * next = strtok(arg_str, &token);
while (next != NULL){
strcpy(args[tokens++], next);
next = strtok(NULL, &token);
if (next == NULL)
args[tokens] = (char *)NULL;
}
exec_command(args);
}