2013-10-22 132 views
0

我無法從函數返回字符串。它在主要方法中打印出垃圾值。我在這個論壇上看到了類似的問題,但該頁面上的結果並沒有幫助我。我不想將另一個變量傳遞給函數。我希望能夠按原樣返回字符串值。我怎麼能這樣做呢?C字符串返回函數返回垃圾

char *LookupPath(char **argv, char **dir) 
{ 
    /* String Name To Be Returned */ 
    char path_name[MAX_PATH_LEN] = {0}; 
    char *result = malloc(sizeof(path_name)); 
    int i; 

    /* Check To See If File Name Is Already An Absolute Path Name */ 
    if(*argv[0] == '/') { 

    } 

    /* Look In Path Directories */ 
    for(i = 0; dir[i] != NULL; i++) { 
     strncat(path_name, dir[i], sizeof(path_name)); 
     strncat(path_name, "/", sizeof(path_name)); 
     strncat(path_name, argv[0], sizeof(path_name)); 
     result = path_name; 
     if(access(result, F_OK) == 0) { 
      printf("result: %s\n", result); 
      return result; 
     } 
     path_name[0] = '\0'; 
    } 

    /* File Name Not Found In Any Path Variable */ 
    return NULL; 
} 

你的幫助是極大的讚賞!

+1

你沒有使用'strncat'正確。最後一個參數應該是要附加的最大字符數*,而不是該字符串應該包含的最大字符數。考慮使用帶有「%s /%s」格式的'snprintf'等。 – dreamlax

+0

你真的應該學習如何使用'gdb'調試器。 –

回答

4
result = path_name; 

應該是:

strcpy(result, path_name); 

或者更好,擺脫path_name並直接使用result

請注意,您應該記住在未使用時釋放result,當它返回時,將其釋放到調用它的函數中。由於您返回NULL失敗,在這種情況下,直接釋放它,或者它是內存泄漏。

而你正在使用strncat錯,請閱讀manual

2

您不能從函數返回本地數組(如path_name)。該本地數組位於call frame之內,返回時彈出。

正如其他人回答說,你應該做的

strncpy(result, path_name, MAX_PATH_LEN); 

文件調用方應釋放結果的慣例。

順便說一句,你的代碼效率很低;你正在分配一個相當大的MAX_PATH_LEN塊(通常是4096),這個字符串通常要小得多。

如果使用GNU的擴展,你可以簡單地使用asprintf(3)(見this),或至少刪除您mallocreturn strdup(path_name);和使用strdup(3)(這是標準的,不需要任何GNU擴展)。

並學習如何使用valgrind

+1

再加上他泄露了「結果」(它最初分配給的結果)。 –

1

由於此行的:

result = path_name; 

重新分配result指向局部變量path_name,其超出範圍時的函數返回。這也意味着你有內存泄漏。

而不是使用臨時path_name變量,直接寫入result

2

您正在爲值path_name分配的值超過其實際可以持有的值。

strncat(path_name, dir[i], sizeof(path_name)); 
    strncat(path_name, "/", sizeof(path_name)); 
    strncat(path_name, argv[0], sizeof(path_name)); 

應該是:

sprintf(path_name, "%s%s%s", dir[i],"/",argv[0]); 
+1

不是'%S',而是'%s',格式控制字符串中沒有空格。 –

+0

@BasileStarynkevitch:謝謝您,先生,請注意 – 2013-10-22 06:01:18

+2

如果您知道緩衝區的大小,並且該函數可用,則應該使用'snprintf'來代替,這使得緩衝區溢出變得更加困難。 – dreamlax