-2

In the following program, i am expecting the for loop to stop after 3 elements. But it keeps on going indefinitely and fails later on with a coredump.

  1. is malloc() needed forchar*[]`
  2. would strcmp fail if i memset to 0?

.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
        char* str[10]; memset(str,0,10);

        str[0]=malloc(sizeof(char)*(strlen("Sample")+1));
        str[1]=malloc(sizeof(char)*(strlen("Sample")+1));
        str[2]=malloc(sizeof(char)*(strlen("Sample")+1));

        strcpy(str[0],"Sample");
        strcpy(str[1],"Sample");
        strcpy(str[2],"Sample");



        int i=0;
        for(i=0;strcmp("",str[i])!=0;i++)
        {
                printf("%d\n",i);;
        }
        return 0;
}

Edit: Even with char* str[10]; memset(str,0,10*sizeof(char*)); the code still gives core dump

anurag86
  • 1,635
  • 1
  • 16
  • 31
  • 1. Yes. 2. No. _Some nonsense text to let me post this short comment._ – πάντα ῥεῖ Jun 28 '19 at 16:23
  • You're only zeroing 10 bytes of an array which is 10 pointers. Change that 10 to `10 * sizeof(char *)`. You don't need the `sizeof (char)` inside the malloc's, because that's 1 by definition. Yes, you need to malloc all 10 if you want `strcmp()` to work. `""` and a null pointer are very different things. – Lee Daniel Crocker Jun 28 '19 at 16:25
  • Should check if `str[i]` is not `NULL` before doing the `strcmp` too – Chris Turner Jun 28 '19 at 16:27
  • Even if you do successfully zero out the unused entries in `str[]`, you're still going to have trouble when you try to call `strcmp` on the (probably) NULL pointer. So, yes, you want `for(i=0; str[i] != NULL && strcmp("",str[i])!=0; i++)` (or perhaps the abbreviated `str[i] && strcmp("",str[i])!=0` ). – Steve Summit Jun 28 '19 at 16:27
  • Although it will work on any platform you're ever going to use, strictly speaking using `memset` like this is *not* guaranteed to give you null pointers. – Steve Summit Jun 28 '19 at 16:30
  • Yet another problem is that if you ever store 10 nonempty strings in the array, the loop's going to sail off the end, never finding an empty string, and you're back in SIGSEGV territory again... – Steve Summit Jun 28 '19 at 16:39
  • @user3121023: got it. btw why did erroika say _"In general, having a char*[] does not mean that you necessarily need dynamic allocation and thus no need for malloc."_ – anurag86 Jun 28 '19 at 16:54
  • 2
    That was in answer to your question "is `malloc()` needed for `char*[]`". No, you do not need `malloc` for this program. You don't need it to allocate the three "Sample" strings you're currently allocating, and you don't need it to allocate `str`, either. – Steve Summit Jun 28 '19 at 16:56
  • Can you please clarify whether you are trying to use C or C++? they are different languages – M.M Jul 01 '19 at 03:40
  • @M.M I am working on two different projects. One is in c which i am not used to much. And the other is c++ – anurag86 Jul 02 '19 at 04:05

3 Answers3

3

Summarizing everything stated in comments and other answers, there are at least three (or, if you want to be pedantic, four) problems here:

  1. You need memset(str, 0, 10*sizeof(char *) (but see #4 below).
  2. You need to check for null pointers before calling strcmp, using a condition like str[i] != NULL && strcmp("",str[i])!=0 in your for loop.
  3. If you ever store 10 nonempty strings in the array, the loop's going to sail off the end, never finding an empty string.
  4. (pedantic) memset is not a good way to initialize an array of null pointers. (Strictly speaking it's not guaranteed to work at all.) As suggested by @user3121023 in a comment, a better way is char *str[10] = { NULL }.

Instead of using an empty string (or a null pointer) as a marker for the end of your array of strings, you might consider keeping an explicit count in a separate variable. That's probably the more common approach.


Addendum. You were asking whether you needed to allocate the strings. Memory does need to be allocated for the strings, but you do not necessarily need to dynamically allocate it by calling malloc. There are at least three ways to achieve the necessary allocation, and in two of them, the compiler does it for you. Here's an example of all three:

char sample1[] = "Sample 1";

char *sample2 = malloc(strlen("Sample 2") + 1);
strcpy(sample2, "Sample 2");

str[0] = "Sample 0";
str[1] = sample1;
str[2] = sample2;
Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • Yes, but i am asking specifically for `char *str; strcpy(str,"sample")` .It is illegal, but eeroika said its not illegal because malloc wasnt done, it is illegal because str is uninitialized. Well when i write `char* str;`, after this what other way than malloc do i have to initialize? – anurag86 Jun 28 '19 at 17:12
  • 1
    @anurag86 Yes, if you call `strcpy`, you have to give it a pointer to memory it can write into. But even then, that still doesn't mean that the *only* way is for it to have been obtained with `malloc`. For example, you could perfectly well do `char sample4[20]; char *ptr = sample4; strcpy(ptr, "Sample 4");`. – Steve Summit Jun 28 '19 at 17:15
2
for(i=0;strcmp("",str[i])!=0;i++)

You do dereference the unitialized pointer

for(i=0;str[i];i++)

But it will not work as this

memset(str,0,10);

Does not initialize the whole array

memset(str,0,10*sizeof(char *);
0___________
  • 60,014
  • 4
  • 34
  • 74
2
  1. is malloc() needed for char*[]`

There is hardly ever a need for malloc in C++.

In C, you usually do need malloc, but only if you need to allocate dynamically.

In general, having a char*[] does not mean that you necessarily need dynamic allocation and thus no need for malloc.

if i do not malloc for every element of array str[] , then wouldn't it be wrong to assign a string without allocating memory for this string?

A char* does not need to point to memory allocated with malloc. It can for example point directly to a string literal (only in C; in C++ you need a pointer to const). Or it can point to memory on the stack.

isn't char *str; strcpy(str,"sample") wrong if i dont allocate memory to str through malloc?

That is wrong, but not because you don't use malloc. It is wrong because you pass an uninitalised pointer to strcpy. Therefore the behaviour is undefined. It has nothing to do with malloc.


  1. would strcmp fail ...

It is unclear what you mean by "fail". There is no output that signifies a failure or error. For some inputs, the behaviour is undefined. While undefined behaviour is a failure of the programmer, there is no guarantee of behaviour that you might consider a failure.

... if i memset to 0?

If you pass a pointer to strcmp that is not a pointer to a null terminated string, then the behaviour of the program is undefined.

In the program that you show, you end up passing uninitialised pointer, or one that was memset to 0, and there is therefore no guarantee for them to be a pointer to a null terminated string. Therefore the behaviour of the program is undefined.

i'm passing a pointer pointing to 0(null), so dereferencing shouldn't face the problem of having no null terminated string right as we dont store anything in null location

Memset to 0 is not guaranteed to be null, as far as the standard is concerned. Even if probably is null on your system, 10 bytes is probably not enough for 4 pointers on that system, as pointed out by @ChristianGibbons, so you haven't actually initialised all of the pointers at all.

Even if you did initialise the pointers to null, a null pointer is not a pointer to a null terminated string, and therefore passing a null pointer to strcmp has undefined behaviour.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • @eeroika : 1. We are talking about C. 2. For `char* str[]`, if i do not malloc for every element of array `str[]` , then wouldn't it be wrong to assign a string without allocating memory for this string? 3. In the 4th iteration, i'm passing a pointer pointing to 0(null), so dereferencing shouldn't face the problem of having no null terminated string right as we dont store anything in null location – anurag86 Jun 28 '19 at 16:42
  • @anurag86 Assuming you indeed had a null pointer, that is exactly the problem. Dereferencing a null pointer is illegal. – Christian Gibbons Jun 28 '19 at 16:44
  • @anurag86 if we are talking about C, then why did you tag the question as [c++]? – eerorika Jun 28 '19 at 16:44
  • @eeroika : For char* str[], if i do not malloc for every element of array str[] , then wouldn't it be wrong to assign a string without allocating memory for this string? BTW I removed the c++ tag. – anurag86 Jun 28 '19 at 16:47
  • @eeroika: `char *str="sample"` . Here `sample` is string literal and str wont need malloc, but `isn't char *str; strcpy(str,"sample")` wrong if i dont allocate memory to str through malloc? Because in the latter case, str is still pointing to some garbage location and copying a string without getting through malloc is illegal. No? – anurag86 Jun 28 '19 at 17:01
  • @erroika: Well when i write `char* str;`, after this what other way than malloc do i have to initialize? In the sample program it indeed is char* arrays which without malloc would be ofcourse uninitialized, unless i store something during declaration itself(in the same line), e.g. `char*str[2]= {"Sample1","sample2"};` – anurag86 Jun 28 '19 at 17:12
  • @anurag86 For example `str = "Sample";` The initialisation does not need to be on the same line; the pointer can be assigned later. But it can be initialised directly. Both when using malloc and when not using it. – eerorika Jun 28 '19 at 17:15
  • By `str = "sample"` in your comment, do you mean `char*str; str="sample"` ? – anurag86 Jun 28 '19 at 17:22
  • @anurag86 You ask what to write after `char* str;`. If you put another `char*str;` after that, then there is a duplicate variable definition. – eerorika Jun 28 '19 at 17:23
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/195709/discussion-between-anurag86-and-eerorika). – anurag86 Jun 28 '19 at 17:26