Note that there are some explanatory texts on larger screens.

plurals
  1. POStrange (Undefined?) Behavior of Free in C
    text
    copied!<p>This is really strange... and I can't debug it (tried for about two hours, debugger starts going haywire after a while...). Anyway, I'm trying to do something really simple:</p> <p><code>Free an array of strings</code>. The array is in the form:</p> <p><code>char **myStrings</code>. The array elements are initialized as:</p> <pre><code>myString[index] = malloc(strlen(word)); myString[index] = word; </code></pre> <p>and I'm calling a function like this:</p> <p><code>free_memory(myStrings, size);</code> where size is the length of the array (I know this is not the problem, I tested it extensively and everything except this function is working).</p> <p><code>free_memory</code> looks like this:</p> <pre><code>void free_memory(char **list, int size) { for (int i = 0; i &lt; size; i ++) { free(list[i]); } free(list); } </code></pre> <p>Now here comes the weird part. <code>if (size&gt; strlen(list[i]))</code> then the program crashes. For example, imagine that I have a list of strings that looks something like this:</p> <pre><code>myStrings[0] = "Some"; myStrings[1] = "random"; myStrings[2] = "strings"; </code></pre> <p>And thus the length of this array is <code>3</code>.</p> <p>If I pass this to my <code>free_memory</code> function, <code>strlen(myStrings[0]) &gt; 3</code> (<strong>4 > 3</strong>), and the program crashes.</p> <p>However, if I change <code>myStrings[0]</code> to be <code>"So"</code> instead, then <code>strlen(myStrings[0]) &lt; 3</code> (<strong>2 &lt; 3</strong>) and the program does <em>not</em> crash.</p> <p>So it seems to me that <code>free(list[i])</code> is actually going through the <code>char[]</code> that is at that location and trying to free each character, which I <em>imagine</em> is <strong>undefined behavior</strong>.</p> <p>The only reason I say this is because I can play around with the size of the first element of <code>myStrings</code> and make the program crash whenever I feel like it, so I'm assuming that this is the problem area.</p> <p><strong>Note</strong>: I <em>did</em> try to debug this by stepping through the function that calls <code>free_memory</code>, noting any weird values and such, but the moment I step into the <code>free_memory</code> function, the debugger crashes, so I'm not really sure what is going on. Nothing is out of the ordinary until I enter the function, then the world explodes.</p> <p><strong>Another note</strong>: I also posted the shortened version of the source for this program (not too long; Pastebin) <a href="http://pastebin.com/vFr2tZDi" rel="nofollow">here</a>. I am compiling on MinGW with the c99 flag on.</p> <p><strong>PS</strong> - I just thought of this. I am indeed passing <code>numUniqueWords</code> to the free function, and I know that this does not actually free the entire piece of memory that I allocated. I've called it both ways, that's not the issue. And I left it how I did because that is the way that I will be calling it after I get it to work in the first place, I need to revise some of my logic in that function.</p> <p><strong>Source, as per request (on-site)</strong>:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;ctype.h&gt; #include &lt;stdlib.h&gt; #include "words.h" int getNumUniqueWords(char text[], int size); int main(int argc, char* argv[]) { setvbuf(stdout, NULL, 4, _IONBF); // For Eclipse... stupid bug. --&gt; does NOT affect the program, just the output to console! int nbr_words; char text[] = "Some - \"text, a stdin\". We'll have! also repeat? We'll also have a repeat!"; int length = sizeof(text); nbr_words = getNumUniqueWords(text, length); return 0; } void free_memory(char **list, int size) { for (int i = 0; i &lt; size; i ++) { // You can see that printing the values is fine, as long as free is not called. // When free is called, the program will crash if (size &gt; strlen(list[i])) //printf("Wanna free value %d w/len of %d: %s\n", i, strlen(list[i]), list[i]); free(list[i]); } free(list); } int getNumUniqueWords(char text[], int length) { int numTotalWords = 0; char *word; printf("Length: %d characters\n", length); char totalWords[length]; strcpy(totalWords, text); word = strtok(totalWords, " ,.-!?()\"0123456789"); while (word != NULL) { numTotalWords ++; printf("%s\n", word); word = strtok(NULL, " ,.-!?()\"0123456789"); } printf("Looks like we counted %d total words\n\n", numTotalWords); char *uniqueWords[numTotalWords]; char *tempWord; int wordAlreadyExists = 0; int numUniqueWords = 0; char totalWordsCopy[length]; strcpy(totalWordsCopy, text); for (int i = 0; i &lt; numTotalWords; i++) { uniqueWords[i] = NULL; } // Tokenize until all the text is consumed. word = strtok(totalWordsCopy, " ,.-!?()\"0123456789"); while (word != NULL) { // Look through the word list for the current token. for (int j = 0; j &lt; numTotalWords; j ++) { // Just for clarity, no real meaning. tempWord = uniqueWords[j]; // The word list is either empty or the current token is not in the list. if (tempWord == NULL) { break; } //printf("Comparing (%s) with (%s)\n", tempWord, word); // If the current token is the same as the current element in the word list, mark and break if (strcmp(tempWord, word) == 0) { printf("\nDuplicate: (%s)\n\n", word); wordAlreadyExists = 1; break; } } // Word does not exist, add it to the array. if (!wordAlreadyExists) { uniqueWords[numUniqueWords] = malloc(strlen(word)); uniqueWords[numUniqueWords] = word; numUniqueWords ++; printf("Unique: %s\n", word); } // Reset flags and continue. wordAlreadyExists = 0; word = strtok(NULL, " ,.-!?()\"0123456789"); } // Print out the array just for funsies - make sure it's working properly. for (int x = 0; x &lt;numUniqueWords; x++) { printf("Unique list %d: %s\n", x, uniqueWords[x]); } printf("\nNumber of unique words: %d\n\n", numUniqueWords); // Right below is where things start to suck. free_memory(uniqueWords, numUniqueWords); return numUniqueWords; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload