C: Memory error while running program

1

I'm trying to write a program that accepts strings (these are given) and then stores them according to their length in another array. After this, the program prints out the amount of the word who have that length. I tried to create this using this code:

#include <stdlib.h>
#include <stdio.h>

void *repeatStr(char *str, int count); 

int main() {

char arr[8][128] = { "Hallo", "Stewardess", "wat", "een", "fijne", "vlucht" };  
int groottes[11] = { 0,0,0,0,0,0,0,0,0,0,0};

    for (size_t i = 0; i <= strlen(arr); i++)   {
        char *word =  arr[i] ;      
        int grootte = strlen(word);
        groottes[grootte] += 1; 
    }

    for (size_t i = 0; i < strlen(arr); i++)    {
        char ret;
        int grt = groottes[i];
        ret = repeatStr('*', grt);
        printf("%d: %s", i + 1, ret);   
     }
}


void *repeatStr(char *str, int count) {     
    if (count == 0) return "";
    char *ret = malloc(strlen(str) * count + count);
    if (ret == NULL) return NULL;
    strcpy(ret, str);
    while (--count > 0) {
    strcat(ret, str);   
  }     
  return ret; 
}

the error I get is:

Exception thrown at 0x0FD53B8D (ucrtbased.dll) in Oefening.exe: 0xC0000005: Access violation reading location 0x00000061.

c
out-of-memory
asked on Stack Overflow Dec 14, 2015 by SpartanHero • edited Dec 14, 2015 by SpartanHero

3 Answers

1

Given this declaration:

char arr[8][128] = { "Hallo", "Stewardess", "wat", "een", "fijne", "vlucht" };  

The two loops are grossly incorrect:

for (size_t i = 0; i <= strlen(arr); i++)   {
    /* ... */
}

Pay attention to compiler warnings, and turn them up if need be. The compiler should be warning you that in strlen(arr), you are passing a pointer to strlen() that is incompatible with its parameter type. Specifically, you are passing a char (*)[128] (pointer to array of 128 char) whereas strlen()'s expects a possibly-const char *.

If you want the number of elements in arr (8), that would be what @NadavL suggested: sizeof(arr) / sizeof(arr[0]). Given that you have space for 8 elements but initializers for only 6, however, I suppose what you really want is

for (size_t i = 0; (i < sizeof(arr) / sizeof(arr[0])) && arr[i][0]; i++)   {
    /* ... */
}

That ensures that i does not exceed the array bound, but stops the iteration if you run out of words before you run out of array. The latter would not be possible, so there would be no need to check for it, if you allowed C to choose the array size for you, by declaring it like this, instead:

char arr[][128] = { "Hallo", "Stewardess", "wat", "een", "fijne", "vlucht" };
answered on Stack Overflow Dec 14, 2015 by John Bollinger
1

First of all

char arr[8][128] = { ... };

can be changed to :

char arr[][128] = { ... };  

The compiler can see how many elements you need so it allocates just enough when you omit the first size. In your case you're allocating space for 8 strings, while you're only initializing 6 of them, which could lead to problems later.

In your first two loops you want to check for the following condition:

i < sizeof(arr)/sizeof(arr[0])

Arrays are zero-indexed, so if your array has n elements, you can access only the following elements:

arr[0], arr[1], ... , arr[n-1]

sizeof(arr) is the total memory occupied by arr. If you want the number of arrays in arr you have to divide it by the size of its elements, so sizeof(arr[0])

There is also an issue with the way you call repeatStr It expects a string, so I assume you want to call it with:

ret = repeatStr(arr[i], grt);

where ret is definded like so:

char *ret;

because it's a string.

answered on Stack Overflow Dec 14, 2015 by Alexguitar • edited Dec 14, 2015 by Alexguitar
0

On the first loop, it seems like you want to iterate through the words in your array.

But instead of doing so, you're going to iterate 8*128 times, as sizeof(arr) will return 8*128 (you allocated 128 bytes 8 times - one for each word).

What you actually want to use is:

    for (size_t i = 0; i <= (sizeof(arr)/sizeof(arr[0])); i++)

That will produce the correct number of word entries in your array.

Additionally, you use:

char ret;
ret = repeatStr("*", grt);

But repeatStr returns a char , and then you treat 'ret' as a char, even though in the function context it's merely a regular char.

Change to:

char *ret;
ret = repeatStr("*", grt);

And it should compile and execute without memory violations.

answered on Stack Overflow Dec 14, 2015 by NadavL • edited Dec 14, 2015 by NadavL

User contributions licensed under CC BY-SA 3.0