我試圖找到某個類型的目錄中的所有文件(此處硬編碼爲tif)並將它們複製到數組中。所有東西都乾淨地編譯(gcc -Wall沒有提供任何錯誤或警告),但是有一些內存問題。儘管我編寫的程序似乎運行得很乾淨(沒有段錯誤),但某些文件名是您在字符串中使用ascii值之外的其他字符時會出現的奇怪字符。這導致我使用valgrind運行,它顯示錯誤(下面的輸出),但我無法找到實際問題。在一些目錄中,valgrind會自我分段(程序在同一個目錄中運行乾淨)。將文件名複製到一個數組中C使用C
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <search.h>
#include <string.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
int exitStatus = 0;
/*------------------------------------------------------------------------------
* array_find
*
* ARGS - Takes a pointer to a string, a pointer to an array of strings, and an
* int representing the length of the array.
*
* RETURN - returns an int indicating the first index of the key in the array,
* or -1 if the key was not found
*-----------------------------------------------------------------------------*/
int array_find(char *key, char *argv[], int argc){
int i;
for (i = 0; i < argc; i++)
{
#ifdef DEBUG_array_find
printf("strncmp(%s, %s, %d) = %d\n", key, argv[i], min(strlen(key), strlen(argv[i])), strncmp(key, argv[i], min(strlen(key), strlen(argv[i]))));
#endif
if (strncmp(key, argv[i], min(strlen(key), strlen(argv[i]))) == 0)
{
return i;
}
}
return -1;
}
/*------------------------------------------------------------------------------
* ends_with
*
* ARGS - str = string to be checked
* sub = string to look for
*
* RETURN - Returns true if str ends with sub or both strings are NULL.
False otherwise.
*-----------------------------------------------------------------------------*/
bool ends_with(char *str, char *sub){
if (str == NULL && sub == NULL)
{
return true;
}
if (str == NULL || sub == NULL)
{
return false;
}
char *last_instance_of_sub = rindex(str, *sub); //Finds the last index of the first char of sub
int sub_len = strlen(sub);
if (last_instance_of_sub == NULL || strlen(last_instance_of_sub) != sub_len)
{
return false;
}
return strncmp(last_instance_of_sub, sub, sub_len) == 0;
}
int main(int argc, char *argv[])
{
/*Parse args*/
DIR *dir;
int index = array_find("-d", argv, argc);
char *dirname;
if (index >= 0)
{
dirname = argv[index + 1];
dir = opendir(dirname);
}
else
{
dirname = getcwd(NULL, 0);
if (dirname == NULL)
{
perror("Error getting current directory name.");
exit(1);
}
dir = opendir(dirname);
}
if (dir == NULL)
{
perror(dirname);
exit(1);
}
#ifdef DEBUG_MAIN
printf("dirname = %s\n", dirname);
#endif
int threads = 1;
index = array_find("-t", argv, argc);
if (index >= 0)
{
threads = atoi(argv[index + 1]);
}
#ifdef DEBUG_MAIN
printf("threads = %d\n", threads);
#endif
struct dirent *entry = readdir(dir);
int num_files = 0;
while (entry != NULL)
{
if (ends_with(entry->d_name, ".tif")){
#ifdef DEBUG_MAIN
printf("%s\n", entry->d_name);
#endif
num_files++;
}
entry = readdir(dir);
}
if (closedir(dir) != 0)
{
perror("Failed to close directory.");
}
#ifdef DEBUG_MAIN
printf("Num files = %d\n", num_files);
#endif
dir = opendir(dirname);
if (dir == NULL)
{
perror(dirname);
exit(1);
}
entry = readdir(dir);
char *file_names[num_files];
int i = 0;
for(; entry != NULL; i++)
{
if (ends_with(entry->d_name, ".tif")){
file_names[i] = strdup(entry->d_name);
if (file_names[i] == NULL)
{
perror("Could not create the filename array.\n");
exit(1);
}
}
entry = readdir(dir);
}
/* #ifdef DEBUG_MAIN*/
for (i = 0; i < num_files; i++)
{
printf("%s\n", file_names[i]);
/* free(file_names[i]);*/
}
/* #endif*/
free(dir);
return exitStatus;
}
Valgrind的輸出:
==24488== Memcheck, a memory error detector
==24488== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==24488== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==24488== Command: ./myprogram -d /home/chris/Pictures/Catalinas\ with\ Christie/Processed/
==24488==
dirname = /home/chris/Pictures/Catalinas with Christie/Processed/
threads = 1
cacti2_lzn.tif
DSC_2139_lzn.tif
DSC_1512_lzn.tif
DSC_1296_lzn.tif
DSC_1577_lzn.tif
DSC_1658_lzn.tif
DSC_1293_lzn.tif
DSC_1631_lzn.tif
DSC_1418_lzn.tif
DSC_1315_2crop_lzn.tif
DSC_1377_lzn2crop.tif
DSC_2167_lzn.tif
1981-1985-HDR3_lzn2.tif
DSC_2129_lzn.tif
DSC_1448_lzn.tif
DSC_1607_lzn.tif
DSC_1564_lzn.tif
DSC_2052-DSC_2072_lzn.tif
DSC_1487_lzn.tif
DSC_1591_2_lzn.tif
DSC_2124_lzn.tif
DSC_1622_lzn.tif
DSC_2157_lzn.tif
DSC_1685_lzn.tif
Num files = 24
cacti2_lzn.tif
DSC_2139_lzn.tif
DSC_1512_lzn.tif
DSC_1296_lzn.tif
DSC_1577_lzn.tif
DSC_1658_lzn.tif
==24488== Use of uninitialised value of size 8
==24488== at 0x4C2D7C2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24488== by 0x4EA4ECB: puts (ioputs.c:36)
==24488== by 0x400D52: main (batch-convert.c:161)
==24488==
==24488== Invalid read of size 1
==24488== at 0x4C2D7C2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24488== by 0x4EA4ECB: puts (ioputs.c:36)
==24488== by 0x400D52: main (batch-convert.c:161)
==24488== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==24488==
==24488==
==24488== Process terminating with default action of signal 11 (SIGSEGV)
==24488== Access not within mapped region at address 0x0
==24488== at 0x4C2D7C2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24488== by 0x4EA4ECB: puts (ioputs.c:36)
==24488== by 0x400D52: main (batch-convert.c:161)
==24488== If you believe this happened as a result of a stack
==24488== overflow in your program's main thread (unlikely but
==24488== possible), you can try to increase the size of the
==24488== main thread stack using the --main-stacksize= flag.
==24488== The main thread stack size used in this run was 8388608.
==24488==
==24488== HEAP SUMMARY:
==24488== in use at exit: 33,243 bytes in 25 blocks
==24488== total heap usage: 26 allocs, 1 frees, 66,051 bytes allocated
==24488==
==24488== LEAK SUMMARY:
==24488== definitely lost: 0 bytes in 0 blocks
==24488== indirectly lost: 0 bytes in 0 blocks
==24488== possibly lost: 0 bytes in 0 blocks
==24488== still reachable: 33,243 bytes in 25 blocks
==24488== suppressed: 0 bytes in 0 blocks
==24488== Rerun with --leak-check=full to see details of leaked memory
==24488==
==24488== For counts of detected and suppressed errors, rerun with: -v
==24488== Use --track-origins=yes to see where uninitialised values come from
==24488== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
Segmentation fault (core dumped)
它是因爲我已經用c在所有時間,但據我所知(從該名男子頁)的strdup應該使用malloc就分配內存堆的字符串的副本。在我想起strdup函數之前,我曾嘗試過手動完成這些操作,並且出現了相同的錯誤。我想也許我的代碼有缺陷,並認爲strdup函數會照顧它,但顯然還有其他一些問題。
誰能告訴我我做錯了什麼?
編輯1: 根據要求,我添加了程序的完整源代碼。另外,對於那些說我要檢查num_files的對象,你會看到,我提前計算了tif文件的數量,所以我知道將被複制到數組中的文件的確切數量,因此檢查索引isn'必要的。
另外,作爲說明,該程序是用DEBUG_MAIN定義的編譯的,所以#ifdef DEBUG_MAIN塊中的任何內容都會運行。沒有定義其他調試標誌。
'entry'的初始值是什麼? – user4815162342
1.如果您發佈了實際的[SSCCE](http://sscce.org/),而不僅僅是一個片段,這將有所幫助。 2.你的程序是否在只有ASCII文件名的目錄下工作? 3。如果沒有相應的源代碼(和行號與它一起),Valgrind輸出完全沒有幫助 – thkala
另外,你是否記得用'i'的最終值更新'num_files'?你是否將'file_names'數組(具有自動存儲類)返回給調用者?發佈一個完整的例子可以解決所有這些問題,而無需詢問。 – user4815162342