0

I have a function C that simulate the Visual Basic mid function. This code works in HPUX but not in RHEL. For example:

main()
{
    char tipo[3];
    char nombre[10];
    strcpy (nombre,"abcdefg");
    strcpy (tipo,lds_mid(nombre,1,2));
    printf ("tipo = %s\n",tipo);
}

Results:

HPUX => tipo = "ab" RHEL => tipo = (empty)

What is the problem ?

char *lds_mid (cadena,inicio,longitud)
    char *cadena; unsigned inicio; unsigned longitud;
{
    int start, length;
    int i;
    char *p;
    int pidio_memoria;

    start = inicio-1;
    length = longitud;
    if (inicio ==0) {
        start = 1;
        length --;
    }
    pidio_memoria = 0;
    for (i=start;(cadena[i]!='\0') && ((i-start)<length);i++) {
        if (i==start) {
            p = (char *) malloc(2*sizeof(char));
            pidio_memoria = -1;
            if (p == NULL) {
                /*printf("\nMemoria agotada\n"); */
                abort();
            }
        }
        else {
            p = (char *) realloc((void *)p,(i-start+ 2)*sizeof(char));
            if (p ==NULL) {
                /*printf("\nMemoria agotada\n"); */
                abort();
            }
        }
        *(p+i-start)=cadena[i];
    } 
    if (pidio_memoria) {
        *(p+i-start) = '\0';

        free(p);
        return p;
    }
    else
        return "";
}
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
Roger
  • 3
  • 3
  • `unsigned inicio; ... = inicio-1` doesn't look nice. – alk Jul 09 '14 at 06:52
  • That's very complicated-looking for what it does. Also, [please don't cast the return value of `malloc()` in C](http://stackoverflow.com/a/605858/28169). – unwind Jul 09 '14 at 07:04
  • This is pretty horrendous code in terms of flow, structure, comments... – copper.hat Jul 09 '14 at 07:07
  • Don't write K&R code, even on HP-UX. If you can't afford the HP ANSI C compiler, get GCC installed instead. Either way, there's no call to write non-prototype functions. – Jonathan Leffler Jul 09 '14 at 07:10
  • possible duplicate of [Using pointer after free()](http://stackoverflow.com/questions/15432123/using-pointer-after-free) – n. m. could be an AI Jul 09 '14 at 08:21

2 Answers2

3

This:

    free(p);
    return p;

is instant undefined behavior as soon as the caller uses the returned string pointer.

Here's my attempt:

char * lds_mid(const char *string, size_t offset, size_t length)
{
  if(string == NULL)
    return NULL;

  const size_t slen = strlen(string);
  if(offset >= slen)
    return NULL;
  const size_t chunk = offset + length > slen ? slen - offset : length;
  char *out = malloc(chunk + 1);
  if(out != NULL)
  {
    memcpy(out, string + offset, chunk);
    out[chunk] = '\0';
  }
  return out;
}

That's about how complicated I would expect such a function to be. There really shouldn't be a need to ever call realloc() in this function.

Note that the above gives the caller ownership of the returned string, it must be free()d when no longer needed. This means your usage snippet doesn't work, since it drops the returned pointer by passing it to strcpy().

It must be:

int main(void)
{
  const char *str = "hello, world!";  /* String to cut part from. */
  char *world = mid(str, 7, 5);
  printf("'%s' ends with '%s'\n", str, world);
  free(world);
  return 0;
}
unwind
  • 391,730
  • 64
  • 469
  • 606
1

You are freeing p before you return to main(). Specifically the issue is here:

if (pidio_memoria) {
*(p + i - start) = '\0';

//free (p);
return p;

Once you have gotten rid of the free(p), you function produces output:

tipo = ab

Good luck.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85