-2

I need to write to shared memory, thus I have

#define FLAGS IPC_CREAT | 0644
int main() {
key = ftok("ex31.c", 'k');
shmid = shmget(key, 3, FLAGS);
shmaddr = shmat(shmid,0,0);    // THOSE LINES WORK AS EXPECTED

char* userInput = malloc(5);
read(0, userInput, 3);  // I want to read "b34" for example, WORKS GOOD
strcpy(shmaddr,userInput);   // THROWS EXCEPTION!
}

it throws me exception in strcat, and if I delete it the exception is thrown in the next line of strcpy. I need to write to the memory "b34\0" (4 chars) and then read it.

fluter
  • 13,238
  • 8
  • 62
  • 100
Zohar Argov
  • 143
  • 1
  • 1
  • 11
  • `read()` doesn't zero terminate `userInput`. So, you can't use `strcat()` with `userInput`. – P.P May 11 '16 at 08:32
  • You should use calloc() instead of malloc() so your memory is all zero bytes to start with. No need to tack on NUL bytes, as long as you read up to one less than the allocated size. And read your C book to find out what a *string* is and which functions take/return strings, and which take/return arbitrary arrays of characters. – Jens May 11 '16 at 08:36
  • change `char* userInput = malloc(5);` to `char* userInput = calloc(5, sizeof(char));` Your `UserInput` "C-String" is not null terminated using malloc and reading 3 bytes only. – LPs May 11 '16 at 08:47

2 Answers2

6

This:

strcat(userInput, '\0');   //THROWS EXCEPTION!!

Is not valid C, and it doesn't "throw an exception" because C doesn't have exceptions. Maybe it crashes, but anyway that should be expected since you're not even writing valid code. Use a compiler that rejects obvious invalid code like this.


Edit: and this:

char* userInput = malloc(5);
read(0, userInput, 3);
strcpy(shmaddr,userInput);

Is invalid because you read three characters, leaving the last two characters in userInput uninitialized, then you call strcpy() which reads a null terminated string from userInput, but you have not null-terminated the string, so it is undefined behavior and anything could happen--including a crash. So try this:

const size_t INPUT_MAX_SIZE = 3;
char userInput[INPUT_MAX_SIZE + 1];
read(STDIN_FILENO, userInput, INPUT_MAX_SIZE);
userInput[INPUT_MAX_SIZE] = '\0'; // add null terminator
strcpy(shmaddr,userInput);

Or better yet:

read(STDIN_FILENO, shmaddr, INPUT_MAX_SIZE);

That is, just read directly to the destination, not a temporary buffer.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    `userInput` isn't zero terminated either. – P.P May 11 '16 at 08:32
  • I have compiled and checked everything.. I just don't know how to simply write "b34' to the shared memory so that i will be able to read it later .. that is all my problem – Zohar Argov May 11 '16 at 08:35
  • @ZoharArgov: It is impossible that you have compiled `strcat(userInput, '\0');` and "checked everything." It's **invalid code which cannot be used**. Your compiler should not even compile it. – John Zwinck May 11 '16 at 08:37
  • it did give me a warning, but has compiled.. anyways, I deleted that line and edited the post. and still, i have trouble with the next line writing to the shared memory. – Zohar Argov May 11 '16 at 08:41
  • 1
    @ZoharArgov: When your compiler gives you a warning, you need to stop and fix it before running the program. Otherwise you waste a lot of time, both yours and ours. – John Zwinck May 11 '16 at 08:45
  • 1
    @ZoharArgov: I have added lots more to my answer. Hope this helps. – John Zwinck May 11 '16 at 08:49
1

Both the function strcat and strcpy expect the arguments to be null-terminated strings, in you case, neither userInput or shmaddr satisfies this condition, that's why you see the program crashes. Try this:

#define FLAGS IPC_CREAT | 0644
int main(void) {
    key = ftok("ex31.c", 'k');
    shmid = shmget(key, 4, FLAGS);  // the buffer needs at least size 4 to hold the 3 char string and the null terminator
    shmaddr = shmat(shmid, 0, 0);

    char* userInput = malloc(5);
    read(0, userInput, 3);
    userInput[3] = '\0';
    strcpy(shmaddr, userInput);
}
fluter
  • 13,238
  • 8
  • 62
  • 100