confusion about size of char

I'm writing a function which returns the number of files/folders in a folder as an integer. The full code (I inserted some cout for diagnostic purposes):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

int no_files(char path[], int sizeof_path);

using namespace std;

int main() 
{
    char path[] = "~/Music";
    FILE *in;
    char buff[512];

    int no_path = no_files(path,sizeof(path));
    cout << no_path;

    return 0;
}

// get number of files/folders in folder 'path'
int no_files(char path[], int pathsize)
{

cout << pathsize << endl;
cout << path << endl;

    char opath[pathsize];

cout << sizeof(opath) << endl;
    strcpy(opath,"ls ");
cout << opath << endl;
    strcat(opath,path);
cout << opath << endl;
    strcat(opath," | wc -l");
cout << opath << endl;

cout << sizeof(opath) << endl;

    FILE * nof_in;
    char nof[100];
    nof_in = popen(opath,"r");
    fgets(nof,sizeof(nof),nof_in);

    return atoi(nof);
}

Path is of size 8 (i.e. pathsize which is sizeof(path) is 8). The code above doesn't produce any error messages, although opath is too small for "ls <path> | wc -l" (<path> there shouldn't be space left for "ls " and " | wc -l"!).

Indeed, if I change "char opath [pathsize]" to "char opath [8]" (which should be the same because pathsize is an integer with the value 8), I get a really long "*** stack smashing detected ***" error message.

Why this strange behaviour, i.e. why doesn't "char opath [pathsize]" (with pathsize=8) produce an error while "char opath [8]" does?
Last edited on
You need to use opendir/readdir/closedir to read the contents of a directory.
You mean, I need opendir to use popen?

If not, I don't think I need opendir to open the directory, because I don't open the directory with C++ but with bash inside popen! (I'm new to C++, it's just a logic conclusion)

Or what do you mean?
writing a function which returns the number of files/folders in a folder as an integer.

Why are you using popen?
Last edited on
Because I'm quite new to C++ and got kinda lost when I tried to do it purely in C++ (with opendir and so on), so I used this C++/Bash-mixture. I know it's most likely not the best solution, but it works. It's my first real C++ programming aside from programming exercises in the C++ course I'm taking, so I'm already glad when the basic stuff works in pure C++ and I get to the solution I want on whatever way...

But that's actually a bit off topic since the real problem here is the one with the char size.
I suppose that your compiler generates slightly different code when using pathsize or 8 as a literal, which also might end up in different stack layouts at runtime. This has to do with compiler optimization. However, in both cases you are writing data to invalid memory areas, which results in undefined behavior sooner or later. The point is that you should never write such code! This is C++ and not C. Please consider some rules not to run into such problems:

- Do not call bash stuff in C++
- Use std::string rather than char[]
- Use strncpy and strncat instead of strcpy and strcat
- Use Boost.Filesystem for your purpose or POSIX opendir/readdir

Good coding style is very important ;-)
I suppose that your compiler generates slightly different code when using pathsize or 8 as a literal, which also might end up in different stack layouts at runtime.
That. But rather compiler optimization, it may be the case that ISO C++ forbids variable length arrays and you are using a compiler extension.
I suppose that the array is dynamic allocated.
Thanks for the explanations regarding the compiler. That seems to be the explanation.
Please consider some rules not to run into such problems:

- Do not call bash stuff in C++

Is there another reason for this than keeping the code "clean" (i.e. not mixing languages)?
- Use std::string rather than char[] [/quote|
I really don't if not necessary because I'm not used at all to variables the length of which I have to explicitly declare (I've only used languages with dynamic variable sizes so far). I've only used char strings in the code above because the functions calling bash commands don't accept std::strings.

Meanwhile, I've written two short functions to convert std::strings to char strings and vice versa, so I can use std::strings and if a function requires char strings, I can easily convert the std::string.

[quote] Good coding style is very important ;-)

I'm aware of this. :) And I also want to write code in good style, I'm perfectionist enough for this. :D

Does anyone have a link to a website describing how to interact with the linux file system (that I don't have to use bash anymore)? I googled quite a bit in this matter, but didn't find a good site. That's why I simply used bash commands instead of having to google for every single function I need to handle files and the file system (a quick and dirty solution for now)...

Edit: I found the boost filesystem library (http://www.boost.org/doc/libs/1_47_0/libs/filesystem/v3/doc/tutorial.html) already mentioned by @mtrenkmann; that seems to be what I need to replace the bash commands.
Last edited on
Topic archived. No new replies allowed.