-2

I know there have been many questions about this but I have tried everything and NOTHING seems to be working.

I have char** and when I try to delete it, I get exception thrown. When I do not delete it, an exception is thrown after the function returns.

I have a function similar to this:

void function(){
     int argc = 5; char** argv;
     argv[0] = "...";
     argv[1] = "...";
     //...
     Package package;
     package.ProcessCommandLineArgs(argc, argv); // this does NOT delete argv

     // THIS FAILS
     for(int i=0;i<5;i++) 
         delete[] argv[i]; // <--- EXCEPTION HERE
     delete[] argv;
}

I have even tried using the function only with this:

void function(){
     int argc = 5; char** argv;
     argv[0] = "...";
     argv[1] = "...";
     //...

     // just declare argv and delete it also fails
     for(int i=0;i<5;i++) 
         delete[] argv[i]; // <--- EXCEPTION HERE
     delete[] argv;
}

I cannot not use char** as I have 4 classes that use the same arguments in a chain of calls so I do not have the option to use vector<string>.

I would appreciate any help. If you want to vote down, do it, but please give me an answer as I have been stumbling with this for hours.

Thanks.

EDIT: I see why this got down-voted and right now I would down-vote it if I had seen it asked on SO. I have since changed all my programs to convert arguments into std::vector<std::string>. If I attempt to delete this question I will be at risk of losing my ability to ask questions since this already has an answer.

Everyone
  • 1,751
  • 13
  • 36

2 Answers2

4

A version of your code that might work is something like this:

#define MAX_SIZE 256 // TODO: set to the size you need...
void function(){
     int argc = 5;
     char** argv = new char*[argc]; // allocate space for the array!
     for(int i = 0; i < argc; ++i) {
         argv[i] = new char[MAX_SIZE];  // allocate space for the array entry!
     }

     // TODO: bounds checking!!!
     strcpy(argv[0], "...");     // set the string to the "..."
     strcpy(argv[1], "...");     // same...



     // cleanup
     for(int i=0;i<argc;i++) 
         delete[] argv[i];
     delete[] argv;
}

In short, only delete[] what you new[], only delete what you new and only free what you malloc/calloc/realloc.

That being said, if you have control over the implementation of ProcessCommandLineArgs, it would be far superior to just pass a std::vector<std::string> and just not worry about the memory management.

Evan Teran
  • 87,561
  • 32
  • 179
  • 238
  • 1
    You, sir, have my full respect. You have provided me with the full example for this unlike anywhere else. You clarified everything needed done. I only had to change `strcpy` to `strcpy_s` and everything is now working I wanted to use `vector` but I would need to change around 10 files to make it work because I have a set of programs that I originally designed to take input args from main. THANK YOU. – Everyone May 03 '17 at 17:24
  • 1
    I seriously cannot thank you enough. I have a deadline due and this was really killing me. The funny part is that the rest of my program is x1000 times more complicated but in that I was avoiding memory management as far as I can. Thank you very much again. – Everyone May 03 '17 at 17:34
  • 1
    @Everyone, no problem. pointers and manual memory management can get rough, sometimes you just need a prod in the right direction :-) – Evan Teran May 03 '17 at 20:06
0

This isn't a surprise; you cannot delete[] something that you did not new[]!

In fact, your entire program has undefined behaviour, because your char** is uninitialised and doesn't point anywhere.

Those elements, if they were valid, point to string literals, which again cannot be delete[]d.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055