我为char ***数组分配空间,该数组存储输入到我的shell程序中的已解析命令和参数。
以下是一些示例命令行输入:
ls -la
cd ..
/usr/bin/wc -l inputs/data/long
这里是char ***数组如何存储命令 - 它用空格分析:
{{"ls", "-la"}, {"cd", ".."}, {"/usr/bin/wc", "-l", "inputs/data/long"}}
这是我如何生成char ***数组:
/*
* initializes history
* returns array of pointers to arrays of pointers to char arrays
*/
char*** inithistory(){
char*** history;
history = (char***) calloc(HIST_SIZE, sizeof(char**));
return history;
}
/*
* adds a tokenized command and arguments to the history
*/
int addToHistory(char*** history, char** tokenized, int* argcnts, int argcnt, int cmdcnt) {
if (cmdcnt >= HIST_SIZE) {
cmdcnt = HIST_SIZE-1;
// remove oldest element and shift others up
for (int i = 0; i < HIST_SIZE-1; i++) {
history[i] = history[i+1];
argcnts[i] = argcnts[i+1];
}
}
// add latest element
history[cmdcnt] = tokenized;
argcnts[cmdcnt] = argcnt;
return 1;
}
/*
* returns the length of a char array
*/
int lengthof(char* string) {
int count = 0;
char temp = string[0];
while (temp) {
temp = string[count];
count++;
}
if (count==0) {
return 0;
}
return count-1;
}
/*
* returns array of pointers to char arrays containing parsed command and arguments e.g. {"ls", "-la"},
* char* input is the command line input
*/
char** tokenize(char* input, int argc) {
char* token;
char** tokenized;
tokenized = (char**) calloc(argc+1, sizeof(char*));
token = strtok(input, " "); // tokenize user input
int i = 0;
while (token != NULL) {
int length = lengthof(token);
if (i == argc-1) {
token[length-1] = '\0';
}
tokenized[i] = (char*) calloc(length, sizeof(char));
tokenized[i] = token;
token = strtok(NULL, " ");
i++;
}
tokenized[argc] = NULL;
return tokenized;
}
当我尝试释放上面的char ***数组时,我收到以下错误:
*** glibc detected *** cs475sh: free(): invalid pointer: 0x000000000150f9b3 ***
======= Backtrace: =========
/lib64/libc.so.6[0x36bb075dee]
/lib64/libc.so.6[0x36bb078c3d]
cs475sh[0x4015e9]
cs475sh[0x400d37]
cs475sh[0x400bf0]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x36bb01ed1d]
cs475sh[0x400a59]
======= Memory map: ========
00400000-00402000 r-xp 00000000 00:14 12006791923606037921 /home/Documents/HW1/shell-handout/cs475sh
00601000-00602000 r--p 00001000 00:14 12006791923606037921 /home/Documents/HW1/shell-handout/cs475sh
00602000-00603000 rw-p 00002000 00:14 12006791923606037921 /home/Documents/HW1/shell-handout/cs475sh
0150f000-01530000 rw-p 00000000 00:00 0 [heap]
36bac00000-36bac20000 r-xp 00000000 fd:00 918063 /lib64/ld-2.12.so
36bae20000-36bae21000 r--p 00020000 fd:00 918063 /lib64/ld-2.12.so
36bae21000-36bae22000 rw-p 00021000 fd:00 918063 /lib64/ld-2.12.so
36bae22000-36bae23000 rw-p 00000000 00:00 0
36bb000000-36bb18a000 r-xp 00000000 fd:00 918804 /lib64/libc-2.12.so
36bb18a000-36bb38a000 ---p 0018a000 fd:00 918804 /lib64/libc-2.12.so
36bb38a000-36bb38e000 r--p 0018a000 fd:00 918804 /lib64/libc-2.12.so
36bb38e000-36bb390000 rw-p 0018e000 fd:00 918804 /lib64/libc-2.12.so
36bb390000-36bb394000 rw-p 00000000 00:00 0
36bd800000-36bd816000 r-xp 00000000 fd:00 918982 /lib64/libgcc_s-4.4.7-20120601.so.1
36bd816000-36bda15000 ---p 00016000 fd:00 918982 /lib64/libgcc_s-4.4.7-20120601.so.1
36bda15000-36bda16000 rw-p 00015000 fd:00 918982 /lib64/libgcc_s-4.4.7-20120601.so.1
7f1088000000-7f1088021000 rw-p 00000000 00:00 0
7f1088021000-7f108c000000 ---p 00000000 00:00 0
7f108c410000-7f108c413000 rw-p 00000000 00:00 0
7f108c42f000-7f108c433000 rw-p 00000000 00:00 0
7ffc6e541000-7ffc6e557000 rw-p 00000000 00:00 0 [stack]
7ffc6e55b000-7ffc6e55c000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted
这是我如何释放阵列:
/*
* char*** history is the array that needs to be freed,
* int cmd is the number of parsed commands in history (char** pointers),
* int* argcnts holds the number of arguments per command (each argument is
* char* - count includes the command itself)
*/
void exitProg(int code, char*** history, int* argcnts, int cmdcnt) {
if (!code) {
exit(code);
}
if (!cmdcnt) {
exit(code);
}
for (int i = 0; i < cmdcnt; i++) {
for (int j = 0; j < argcnts[i]; j++) {
free(history[i][j]);
}
free(history[i]);
}
free(history);
exit(code);
}
我知道在退出程序之前释放内存是多余的,但这是分配所必需的。
我注意到只有在尝试执行free(history[i][j]);
后才会出现错误。
答案 0 :(得分:0)
MikeCAT指出存在内存泄漏:
tokenized [i] =(char *)calloc(length,sizeof(char)); tokenized [i] = 令牌;哦,内存泄漏。
这个问题通过简单的strcpy解决,正如John Bollinger所说:
不仅是内存泄漏,它还可能导致段错误。 你可能想要第二个这样的陈述 strcpy(tokenized [i],token);
释放内存现在可以正常运行。