Pergunta

I have a problem with my function.

char *readFnName(char *fnString, int n, int offset, int *size) {
    char *fnName;
    int nameBuffer, i, j;

    i = offset;
    j = 0;
    nameBuffer = 8;
    fnName = (char *)malloc(nameBuffer);

    while(*(fnString + i) != '(' && i<n) {
        *(fnName + j++) = *(fnString + i++);
        if (j>=nameBuffer) {
            nameBuffer += 8;
            fnName = (char *)realloc(fnName, nameBuffer);
        }
    }

    *(fnName + j++) = '\0';
    *size = j;

    return fnName;
}

I add this function a string, and this is read it well, but i run this function in a loop, and in the 3rd iteration this line crushed:

fnName = (char *)malloc(nameBuffer);

I get a message in netbeans debugger:

malloc(): memory corruption: 0x08a62218

I use netbeans and lubuntu.

Foi útil?

Solução

There's no problem with the code you posted. The runtime error message indicates that there may be heap corruption earlier on in the program, which is being shown up by a later call to an *alloc function.

Try running valgrind on the whole program, it may find something. Failing that, check carefully over code that is using malloc'd buffers to make sure it does not overflow them. You may have to divide-and-conquer to figure out which part of the program has the problem.

Outras dicas

 fnName = (char *)realloc(fnName, nameBuffer);
  1. realloc extends your memory by re-allocating more memory for you. If the extra memory that you asked for cannot be given in the same contiguous area that your old fnName memory is located, the allocator will go grab your allocation block from another place in memory. This means that all of the pointers still pointing to the old fnName memory area (for example another pointer pointing to *(fnName + N)), are still pointing there even though the allocator gave you a new address for fnName so that you could have all of the memory that you requested. Those pointers are called dangling pointers, because they point to de-allocated memory that the program does not own anymore. This is why you get the "memory corruption" message. The OS is telling you that your program tried to access memory that it does not own. This happens when your program uses those dangling pointers as if they still pointed to allocated memory.

  2. realloc works fine unless you ask for more memory than the allocator can provide contiguously from your current address. If it can't provide the memory contiguously, it will go grab it from somewhere else and return another memory address to you.

  3. To fix this, you have to reassign all the pointers still referencing the old memory that is re-allocated to the new memory address. Since you can't really predict when you need to do this and you don't want to write unnecessary code, and since C does not have classes, you should consider allocating a large enough memory pool in the beginning of your program. Then you can write a simple allocation/de-allocation algorithm that allows you to grab memory from it during your functions. Doing this will teach you more about allocating contiguous memory.

    char* pool;
    if ((pool = malloc(sizeOfPoolInBytes)) == NULL)
      merror();
  1. Take a look at your modified function below:
#include<stdlib.h>
#include<iostream>
using namespace std;

char* readFnName(char* fnString, int n, int offset, int* size){
  char *fnName = NULL;
  int nameBuffer = 8;
  int i = offset;
  int j = 0;
  int count = 0;
  int fnNameIndex = 0;

  //-------------------------------------------------------- Since you want to copy everything but '(' find out how 
  //-------------------------------------------------------- long fnString is without all the '(' characters.
  for( int k = 0; k < n; k++)
  {
    if( *(fnString + k) != '(' )
    {
      count += 1;
    }
  }

  //-------------------------------------------------------- Now, just allocate a string to store the result
  fnName = malloc(count);

  //-------------------------------------------------------- Now, copy everything but the '(' character
  for( int p = i; p < n; p++){
    if( *(fnString + p) != '(')
    {
      if(fnNameIndex < count)
        {
          *(fnName + fnNameIndex) = *(fnString + p);
          fnNameIndex++;
        }
    }
  }

  *size = fnNameIndex;//----------------------------------- This will give the accurate size in case the offset is not = 0
  return fnName;
}

int main(){

  char* string = NULL;
  int n = 5;
  string = malloc(n);
  string[0] = 'a';
  string[1] = 'b';
  string[2] = '(';
  string[3] = 'c';
  string[4] = '\0';

  char* newString = NULL;
  int newStringSize = 0;
  int* ptrSize = &newStringSize;
  newString = readFnName(string, n, 0, ptrSize); 

  for(int i = 0; i < n; i++){
    printf("%c\n", string[i]);
  }

  printf("\n");

  for(int j = 0; j < *(ptrSize); j++){
    printf("%c\n", newString[j]);
  }

  free(string);
  free(newString);

  return 0;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top