So, I've been working on a socket messaging project on my free time, and I have not been able to get past the problem of the user's input erasing every time a new message is printed. I'm trying to avoid ncurses
because it doesn't do well with threads. How can I get thread_function
to access the string
variable (thread_function
is just a function I've been using to test how the program would perform when messages are printed in a thread, as they will be when the socket programs are implemented)? Here's some relevant code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>
char *string;
int thread_function(void *) {
while (1) {
sleep(1);
printf("\n\e[1F\e[2K%s\n> %s", "Hello, world!", (char *) string);
fflush(stdout);
}
return 0;
}
int main(int argc, char **argv) {
thrd_t thread;
thrd_create(&thread, thread_function, NULL);
string = malloc(2);
char character;
int position;
while (1) {
printf("> ");
memset(string, 0, 2);
character = 0;
position = 0;
while (1) {
character = getchar();
if (character == '\n') break;
string = realloc(string, position + 1);
string[position++] = character;
}
string[position] = '\0';
printf("\e[1F\e[2K%s\n", string);
}
free(string);
thrd_join(thread, 0);
}
I've tried thread mutex
es and atomic
variables and locks, as well as making the string
variable volatile
. I've also tried passing a pointer to the string
variable to the thread as an argument.
None of the problems have anything to do with multi-threading. This is all fundamental string handling bugs, as explained at How should character arrays be used as strings? and Common string handling pitfalls in C programming.
Bugs:
memset(string, 0, strlen(string));
At this point string
is not initialized because this very line is supposed to initialize it. And so you can't call strlen
here.string = realloc(string, sizeof(char) * 1);
doesn't make any sense since the string already has that length (1 byte).string[strlen(string)] = character;
again this allocated memory, now 2 or more bytes, has not been initialized so you cannot call strlen
. Before you call strlen
there must be a null-terminated string present.string[strlen(string)] = '\0'
is senseless.malloc
and realloc
calls.One easy fix is to keep track of the allocated size by malloc
/realloc
in a separate variable rather than relying on string length.
Note that sizeof(char)
is always 1 so x * sizeof(char)
is just bloat guaranteed to be equivalent to x * 1
.