0

here is my two functions :

void base(char *str)
{
    char *without_spaces;
    without_spaces = remove_spaces(str);                                   
    printf("Without spaces length : %d \n", strlen(without_spaces)); // SEGFAULT HERE !
    free(without_spaces);
}

char *remove_spaces(char *source)
{
  char *result;
  int i = 0;
  result = malloc(strlen(source) + 1);
  while (*source != 0)
  {
     if (*source != ' ') {
      result[i] = *source;
      i++;
     }

     source++;
  }
  result[i] = '\0';
  // If I make the printf here it's work's
  return (result);
}

Here is how I call the base function (the chars provide from the stdin)

int main()
{
  unsigned int maxsize = 324220;
  unsigned int size;
  char *str;
  char buffer[8096];
  unsigned int  i;
  unsigned int  p;
  if ((str = malloc(maxsize + 1)) == NULL)
    return (my_error(RUNTIME_ERROR_MSG, RUNTIME_ERROR_MEMORY));
  p = 0;
  while (p < maxsize && (size = read(0, buffer, 8096)) > 0)
  {
    i = 0;
    while (i < size && p < maxsize)
    {
      str[p] = buffer[i];
      i = i + 1;
      p = p + 1;
    }
  }
  str[p] = '\0';
  base(str);
  return (0);
}

There are an segfault when I use this code with a really big str (approximately 500 000 chars) but it's works when I use it with less chars (like 50 000).

Why ? It's works if I remove the printf in the base function and make it in the remove space function like I have commented it.

Thank's ;)

EDIT: here it's valgrind output (with -g flag compiled)

==27259== Memcheck, a memory error detector
==27259== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==27259== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==27259== Command: ../a.out
==27259== 
Without spaces length : 324987
==27259== HEAP SUMMARY:
==27259==     in use at exit: 324,221 bytes in 1 blocks
==27259==   total heap usage: 3 allocs, 2 frees, 649,466 bytes allocated
==27259== 
==27259== LEAK SUMMARY:
==27259==    definitely lost: 324,221 bytes in 1 blocks
==27259==    indirectly lost: 0 bytes in 0 blocks
==27259==      possibly lost: 0 bytes in 0 blocks
==27259==    still reachable: 0 bytes in 0 blocks
==27259==         suppressed: 0 bytes in 0 blocks
==27259== Rerun with --leak-check=full to see details of leaked memory
==27259== 
==27259== For counts of detected and suppressed errors, rerun with: -v
==27259== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
23
  • What did your debugger tell you ? Commented Nov 4, 2016 at 19:56
  • 1
    are you sure str is properly NULL-terminated? Commented Nov 4, 2016 at 19:57
  • 2
    Have you checked the return value from malloc() before you use it? It can fail and return NULL — but your code assumes it is valid. It is possible that your system won't let you allocate 0.5 MiB of data, though it is unusual. Or you have some other operation that is messing up the heap from which malloc() allocates its data. Commented Nov 4, 2016 at 20:01
  • 1
    The valgrind output doesn't show a seg fault, so it isn't of any direct relevance to the question. The interesting valgrind output would be from a run where the program crashes with the segmentation fault. Commented Nov 4, 2016 at 20:04
  • 1
    When I run your code on a file with 357938 bytes of data, your program lists the answer as 324220. That is, it correctly ignores the excess data that won't fit into the allocated space. The file I used is actually a random set of month names in English, one per line, 50,000 lines. I was testing on macOS Sierra 10.12.1 with GCC 6.2.0. (I don't have a working valgrind on this machine at the moment, sadly.) Commented Nov 4, 2016 at 20:28

1 Answer 1

2

i think thoses functions a bit confusing in the logic, the function who read also does the copy, i'd prefer an aproch where there is a function to calculate the good lenght to malloc, then one to copy, and finally one to read from stdin

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

static size_t   ft_strlen(const char *str)
{
    size_t      len;

    len = 0;
    while (*str != '\0')
    {
        if (*str != ' ')
            len++;
        str++;
    }
    return (len);
}

char            *delete_spaces(const char *str)
{
    const size_t        size = ft_strlen(str);
    char                *nospaces;
    size_t              p;

    if (!(nospaces = malloc(size + 1)))
        return (NULL);
    p = 0;
    while (*str)
    {
        if (*str != ' ')
            nospaces[p++] = *str;
        str++;
    }
    nospaces[p] = '\0';
    return (nospaces);
}

int             main(int ac, char **av)
{
    char    *nospaces;

    if (ac < 2)
        return (0);
    nospaces = delete_spaces(av[1]);
    printf("nospaces: %s\n", nospaces);
    free(nospaces);
    return (0);
}

/a.out 'testing a string with somes spaces' gives: nospaces: testingastringwithsomesspaces

then in this case you will also malloc just the good size (source - number of spaces + 1)

by the way if you compile with clang you can add: -fsanitize=address -g3

to the compilation flags using -Weverything -Werror is also a very good practice when trying to find this kind of bugs

Sign up to request clarification or add additional context in comments.

1 Comment

the () around my returns are just because of the coding rules i'm using

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.