taking length of predefined string vs getting one from input [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I seem to be unable to understand why do these two cases behave differently:
const char* TEXT = "hello world!";
int length = (int) strlen(TEXT);
char* array[length];
this is ok, however this one:
char* text;
scanf("%[^\n]s", text);
// input "hello world!" and press enter
int length = (int) strlen(text);
char* array[length];
ends with a segmentation fault
what am I missing?

For the scanf call, text parameter, you do not allocate any memory. You also do not initialize the variable to a value. This results in scanf writing to random memory, which causes your segmentation fault.
To fix this issue you need to allocate a buffer of a reasonable size:
char* text = malloc(1024);
1024 is the maximum size that you expect the input data to be. This, however, still leaves the code vulnerable to buffer overflows. To prevent buffer overflows you can inform scanf that text is of a certain size; look for the answers here
If you do not want to allocate the memory yourself, scanf can do it for you:
Note that the POSIX 2008 (2013) version of the
scanf()
family of functions supports a format modifier m (an
assignment-allocation character) for string inputs (%s, %c, %[).
Instead of taking a char * argument, it takes a char ** argument,
and it allocates the necessary space for the value it reads:
char *buffer = 0;
if (sscanf(data, "%ms", &buffer) == 1)
{
printf("String is: <<%s>>\n", buffer);
free(buffer);
}
If the sscanf() function fails to satisfy all the conversion
specifications, then all the memory it allocated for %ms-like
conversions is freed before the function returns.

Related

Problem of a string read in function system() (probably due to a bad malloc) [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
chain1 = (char *) malloc(5*sizeof(char*) + 1);
strcat(chain1, "cp mediaPlayer.exe ");
strcat(chain1, actual->chain);
strcat(chain1, "\n");
system(chain1);
Hi everyone, i have an issue with my actual string... I'm trying to create a string that will be used in the function system that is called by the shell on my linux but the fact is that it can read my string because it doesn't start with cp mediaPlayer.exe but this --> sh: 1: ��P�Pcp:
Then, the error below is sent to me on my shell and i really don't know how to fix it.
sh: 1: ��P�Pcp: not found
I'm on it for 2 days but i just couldn't find a solution if someone can help me ? Thanks by the way !
chain1 = (char *) malloc(5*sizeof(char*) + 1);
This will allocate enough space for five character pointers plus an extra byte. A pointer is not the same as a character, it tends to be either four or eight bytes currently but can actually be any size. You probably want sizeof(char) but, since that's always 1, you can just ignore it in multiplications.
You probably also want a number higher than five since that's not even enough to store your fixed prefix.
In addition, the current content of that allocated block will be arbitrary so strcat is not the first operation you should be performing on it (since that requires a valid C string).
This is almost certainly the cause of your "string starts with rubbish" problem. A strcpy would be better as the first operation, or just use sprintf to do the whole thing at once, rather than a strcpy/multiple-strcat sequence.
And, finally, a command passed to system does not need a trailing newline.
A better method may be something like:
static const char prefix[] = "cp mediaPlayer.exe ";
char *chain1 = malloc(sizeof(prefix) + strlen(actual->chain));
if (chain1 != NULL) {
sprintf(chain1, "%s%s", prefix, actual1->chain);
}
Space for the terminating \0 is accounted for my using sizeof on the string rather than strlen. The former includes space for the terminator. And note the check for a failed malloc, this is something you should always do if you want robust code. I shouldn't need to mention that, should chain1 end up being NULL at the end of this code block, you should not pass it to system.
In your code the malloc size has nothing to do with the data you are putting into it.
You need
size_t len = strlen("cp mediaPlayer.exe ") +
strlen(actual->chain) +
strlen("\n") + 1; // +1 for terminating 0.
chain1 = malloc(len);
After that your first strcat may fail because the allocated buffer may not (probably won't) contain a null terminated string. Either add chain[0] = 0; or change the first strcat to strcpy.

Difference between gets() and scanf("%s") [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I declared a character pointer, and used it for to scan a string in runtime; I don't know the number of characters that I'm going to enter, so I didn't use calloc or malloc. The program ends when it reached the line scanf("%s", NewMsg_au8).
I'm using CodeBlocks 17.12 editor.
I tried hard coding one of the input case like, NewMsg_au8="0123456789ABCDEF"; — that works fine.
uint8 * NewMsg_au8;
scanf("%s",NewMsg_au8);//<==
printf("Your entered message is: %s\n",NewMsg_au8);
return NewMsg_au8;
gets(s) and scanf("%s", s) are both unsafe and potentially incorrect because:
with those calls as shown, there is no way for either function to determine the maximum number of characters to store into the array pointed to by s, hence overlong input will cause a buffer overrun leading to undefined behavior.
in your case, it is even worse as s is an uninitialized pointer, so both functions would try a store data into a random address in memory causing undefined behavior in all cases.
gets() cannot be used safely and has been deprecated in and then removed from the C Standard.
However, scanf() can be given a limit with a numeric value between % and s:
#include <stdio.h>
#include <string.h>
char *read_string(void) {
char buf[100];
if (scanf("%99s", buf) == 1) {
printf("Your entered message is: %s\n", buf);
return strdup(buf); /* return an allocated copy of the input string */
} else {
/* no input, probably at end of file */
return NULL;
}
}
Note how only 99 characters can be stored into the array buf to allow for the null byte terminator that marks the end of a C string. The %99s conversion specification lets scanf() store at most 100 bytes into buf, including the '\0' terminator.
That is a typical beginners error. You do not save data in pointers (with gets() or scanf()) but in buffers.
Therefore, you have 2 solutions:
Use an array big enough to hold the data. You have to decide yourself what "big enough" means, according to the details of your application.
Use a pointer, and then allocate memory with malloc() - the size, again, you have to decide it. Do not forget to deallocate the memory when you no longer need it.
I tried hard coding one of the input case like, NewMsg_au8="0123456789ABCDEF"; — that works fine.
That is normal, because in that case the compiler automatically allocates enough memory to hold the string.
Please always remember when working with strings: you always need to allocate an extra byte for the terminating null character - the mark of the end of the string. Otherwise, you will need to ask questions again :)

strlen doesn't return the correct value with pointer to an array [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have the following code:
char* realtor_command[120];
for(int i=0;i<REALTOR_MAX_COMMAND_LENGTH;i++){
realtor_command[i]=malloc(sizeof(120));
}
realtor_command[0]="test_string"
realtor_command[1]="next_test_string"
When I use strlen(realtor_command[0]) I get wrong value, I read in previous questions this happens because its an array and not pointer, yet I haven't found any fix for this problem.
My question is if there is anyway to get the length of realtor_command[i]?
Thank you very much.
EDIT :
This is how I invoke strlen :
char* matrix=malloc(strlen(realtor_command[8])+1);
In this code:
char* realtor_command[120];
for(int i=0;i<REALTOR_MAX_COMMAND_LENGTH;i++){
realtor_command[i]=malloc(sizeof(120));
}
You create an array of 120 strings, then loop through REALTOR_MAX_COMMAND strings (presumably this should be 120?) and set them to newly allocated 4- or 8-byte strings (sizeof(120) means sizeof(int) which is either 4 or 8 bytes). Since those strings are newly allocated, they will contain arbitrary data, and may not end with a null-terminator.
This is important because strlen() just loops over the string until it finds a null terminator, so it can't work with non-null-terminated strings.
You could add a null terminator yourself, but then the strings would contain arbitrary garbage up to the end of the string, and they may have null terminators inside them. You could make them start with a null-terminator, but then strlen() would always return 0.
What might be better is to allocate these strings when you actually fill them, and leave them as null pointers until then:
char* realtor_command[120];
for (int i = 0; i < 120; i++) {
realtor_command[i] = NULL;
}
char input_buffer[REALTOR_MAX_COMMAND];
// Read in one string, then copy it so we can re-use the buffer
fgets(input_buffer, REALTOR_MAX_COMMAND, stdin);
realtor_command[0] = strdup(input_buffer);
This will also avoid the memory leak in your code.
Note that you'll probably want to make sure the string read by fgets contains a newline, to make sure the input fit in your buffer:
if (strstr(input_buffer, "\n") == NULL) {
// error, input didn't fit in our buffer!
}

invalid conversion from `char' to `char*' [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
code is :
int main() {
int i,last;
char TXT[500];
printf("Donnez un exemple ?\n");
gets(TXT);
last = strlen(TXT);
for(i=0;i<50;i++){
if (i==0){
strcpy(TXT[1],TXT[0]);
} else {
strcpy(TXT[i-1],TXT[i]);
}
}
getch();
return 0;
}
error in line : strcpy(TXT[1],TXT[0]);
What is the cause of the problem ?
The strcpy function takes two char* (technically, a char* and a const char*). Moreover, it is not allowed to pass strcpy overlapping buffers.
It looks like you wanted to write
TXT[i-1] = TXT[i];
(this would delete the leading character from the string).
for(i=1 /* one, not zero */ ; i<50 ; i++) {
TXT[i-1] = TXT[i];
}
Good, but I want to use strcpy. How?
You are not allowed to use strcpy without an intermediate buffer. If you must use strcpy, do it like this:
char TXT[500], TMP[500];
printf("Donnez un exemple ?\n");
fgets(TXT, 499, stdin);
strcpy(TMP, &TXT[1]); // Note that 'for' loop is no longer required
TXT is an array of 500 characters.
So, TXT[1] and TXT[0] are individual characters (just one single letter).
TXT[0] is the very first character in the array.
TXT[1] is the second character in the array.
The function strcpy expects you to pass POINTER-to-characters (type char*) for both parameters.
And instead, you're passing a single character.
Can you explain what the purpose of this program is?
Maybe we can help you fix it then.
TXT[i] is of type char. But strcpy expects parameters of type char* since it operates on null-terminated strings. Hence the compilation error.
As for how to fix it, that depends on what your code is trying to do. Perhaps all you meant to do was
TXT[1] = TXT[0];
STRING FUNCTIONS WORKS ON STRING NOT ON CHARACTERS
ARE YOU TRYING TO SWAP THE WORDS OR CHARACTERS ?

Arrays Stack Overflow [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
#include
int main(void)
{
char str[100]="88888888888888";
char t[20]="";
gets(t);
puts(str);
puts(t);
return 0;
}
The first line
555555555555555555555555555555555
is put in.
Why str is 55555555555? Why str isn't 88888888888888888 or 55555555555588888?
You overriden the t buffer, and reached the str buffer, where the rest of the input, and the null terminator was set. And puts prints only until the null terminator.
Pretty much looks like that:
[ t (20) ][str(100) ]
55555555555555555555 5555555555555\0
Note that although t is declared as char[20], when you print it you get the full input (longer than 20), since puts stops at the null terminator (again).
BTW, this is a buffer overflow, not a stackoverflow, but stack overflow is possible on this codeas well.
As Binyamin said it is caused by the overflow you trigger because of the input string being too long. However it is a bit random thing - sometimes the two memory allocations will happen just next to each other and the string will extend to the neighbouring variables, sometimes it might not happen.
I advise you to place guard conditions for such kind of overflows.
If you see in the gets documentation:
Notice that gets does not behave exactly as fgets does with stdin as
argument: First, the ending newline character is not included with
gets while with fgets it is. And second, gets does not let you specify
a limit on how many characters are to be read, so you must be careful
with the size of the array pointed by str to avoid buffer overflows.
In your case if you do not know the size apriory maybe it is better idea to use fgets as it is more secure (though a bit slower).
When you enter a string of more than 20 5s, it overruns the buffer that was allocated to t and extends into the buffer that was allocated to str.
Then it displays the contents of str, which is the string you entered, starting at the 21st character.
Finally, it displays the contents of t, but since that string doesn't end with a null character, it continues displaying memory (which is the buffer assiged to str) until it encounters the null character after all the 5s.
In order to avoid those allocation overlapping issues you can try this alternative, so that the allocation takes place at runtime if I'm not wrong:
#include <iostream>
int main(void)
{
char *str;
char *t;
str = new char(100);
str = (char*)"88888888888888";
t = new char(20);
std::cin >> t;
puts(str);
puts(t);
return 0;
}

Resources