I'm doing programming which can traverse subdirectory and show lists.
If I check just file part, it was not problem. But when I do directory part,
and have to recurse program itself(I marked as "from this part"),
it show strcat segment error.
I'm thinking it's problem if string and char* recalling directory.
But I don't know exactly.
Can you guys help me? Thanks you in advance.

#include <stdio.h>
#include <getopt.h>
#include <iostream>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fstream>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

void list_dir(char* dir1_nm, char* output)  //List directory function
{
	DIR *pdir;  //Open directory variable
	pdir = opendir(dir1_nm);
	int icount = 0;	//Count for file number
	char* in_addr = dir1_nm; 
	struct dirent *entry;   //Directory read structure 
	struct stat statbuf;    //File inode information structure
	char* dir2_nm;   //Passing subdirectory name
	char* file_nm1;  //Making absolute path

	ofstream myout; 
	myout.open(output);

	while ((entry = readdir(pdir)) != NULL)  
	{		
		stat(entry->d_name, &statbuf); //Using file name, getting link info	
		if (strcmp(entry->d_name, ".") == 0)  //If current directory, don't process
			continue;
		else if (strcmp(entry->d_name, "..") == 0) //Don't process parent directory
			continue;
		else if((entry->d_type) == DT_REG) //Process regular file
			{
				strcpy(file_nm1, in_addr);
				strcat(file_nm1, "/");
				strcat(file_nm1, entry->d_name);
				cout << "file_nm1 = " << file_nm1 << endl;
			}  //end else
/* From this part */
		else if((entry->d_type) == DT_DIR)
	  		{
				cout << "directory is " << entry->d_name << endl; 
				//strcpy(file_nm1, in_addr);
				//strcat(file_nm1, "/");
				//strcat(file_nm1, entry->d_name);	
				dir2_nm = entry->d_name;
				chdir("dir2_nm");
				cout << "dir2_nm is " << dir2_nm << endl; 

				list_dir(dir2_nm, output);
			}
/* Until here */
	closedir (pdir);   //Close reading input directory
       }
}


int main(int argc, char * argv[])
{
char* dir_nm;
extern char *optarg;
extern int optind, optopt;

dir_nm = argv[2];
list_dir(dir_nm, argv[2]);  //List directory function
}

Dani AI

Generated

— the segfault is caused by writing into memory that was never allocated or is not owned by the program; spotted the core problem. Several definite bugs are visible in the posted code: pointers such as file_nm1 and dir2_nm are declared but never given storage before strcpy/strcat are used on them (that is undefined behavior). chdir("dir2_nm") uses a literal string instead of the variable, closedir is called inside the readdir loop (it should be after the loop), and the output file is opened repeatedly inside the traversal (causes truncation/inefficient behavior). Also, calling stat(entry->d_name) without a path relies on the current working directory and will fail unless the working directory was changed intentionally.

Recommended, low-effort fixes:

  • Stop using raw char* buffers. Build paths with std::string (or allocate a buffer sized by PATH_MAX) and call stat on the full path. For example, construct full = std::string(dir) + "/" + entry->d_name and use stat(full.c_str(), &sb).
  • Do not rely on d_type for portability; use stat/S_ISDIR when d_type is DT_UNKNOWN (some filesystems do not set it). See readdir/dirent details: man readdir.
  • Open the output file once (outside recursion) or pass an ofstream reference. Close the directory after the loop, not inside it.
  • Avoid chdir for recursion; pass the next path to the recursive call.

If willing to modernize, use C++17 std::filesystem::recursive_directory_iterator to handle traversal safely and portably: std::filesystem::recursive_directory_iterator.

Debugging tips: run under AddressSanitizer (-fsanitize=address) or Valgrind to see invalid writes/read-after-free errors (Valgrind: https://valgrind.org/). Check every return value (opendir/readdir/stat) and print the constructed path just before calling stat or recursing.

Recommended Answers

All 2 Replies

i Know ure new to posting here so... please read the "Before you Post" guides in the forum list. USE CODE TAGS!

You are attempting to strcat() to a variable that cannot be added to.

What address have you loaded into dir_nm ? That address space is not completely under your control (for example, how large is the space, enough to add characters to?) so you should not be changing it. You need to create you own space and load values into that space instead -- space you control.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.