This program crashes at the point i=(strlen(data)); with the message
No source available for "strlen() "
But Why?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void) {
char data[]="Hallo";
char buffer[100];
if (strlen(data)!=0)
{
size_t i=0;
i=(strlen(data));
snprintf(buffer,i,"Data: %s \n",data);
return strlen(data)+1;
}
return -1;
}
The error message you cite does not sound like a crash. More like a debugger trying to step into a system library function.
I suspect the cause of the problem is
snprintf(buffer,i,"Data: %s \n",data);
The i here is the "buffer size". i is also the length of data. So you're writing a string to a buffer which is longer than the buffer size. The effect is that snprintf() truncates the output, so not the entire data string will be written.
In fact, Data: is six characters long, that's longer than i (5). So maybe what's happening is that snprintf never makes use of the %s modified, which somehow breaks the stack?
Try replacing i with sizeof(buffer) and see whether that works better.
I just ran this program in Eclipse, and it works fine. It sounds like you are stepping through the code line-by-line and when you get to the strlen call you do a "Step-Into"(F5) instead of "Step Over"(F6). So Eclipse is trying to debug strlen.
Either way, this is an Eclipse issue and I suggest you add an Eclipse tag to the question.
Related
I stumbled upon a problem while going through some unit tests, and I am not entirely sure why the following simple example crashes on the line with sprintf (Using Windows with Visual Studio 2019).
#include <stdio.h>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "en_US.utf8");
char output[255];
sprintf(output, "simple %ls text", L"\u00df\U0001d10b");
return 0;
}
Is there something wrong with the code?
char is 8-bit and wchar_t is 16-bit. When you try to convert the two, you will have to use functions like MultiByteToWideChar to convert between the two.
When you try to use Unicode strings in a multi-byte function, it causes buffer overflow, which might be the cause of your crashes.
Try using swprintf_s instead.
So I have looked into this problem as thoroughly as I could however I have been unable to identify a solution (Very new to programming).
Basically I am trying to read in a .txt file, however as soon as I ask the user to input the name of the file with the get_s function, I get error C2660 - "error C2660: 'gets_s': function does not take 1 arguments".
Here is an example of my code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
FILE *fileread1;
char file1[10];
char read_char1;
char ch;
{
printf("Enter a filename : ");
gets_s("file1.txt");
fileread1 = fopen("file1.txt", "r");
Thanks to everyone that has a look, I appreciate the problem is likely something glaringly obvious, however I am quite new to programming. Many thanks!
gets_s takes two arguments, not one. Here is a reference: http://en.cppreference.com/w/c/io/gets.
You should not be using this function. Rather, you should be using fgets. It is my understanding that gets and gets_s both do not protect against buffer overflow.
To use fgets as you would use gets, simply pass stdin as the input file pointer. Here is a usage example:
char buffer[100];
fgets(buffer, 100, stdin);
Here is a good resource for fgets that goes into more detail: https://www.freebsd.org/cgi/man.cgi?query=fgets&sektion=3
Correction
After some research, gets_s appears to be a version of gets that protects against buffer overflow, however I couldn't find it in stdio.h on my OSX machine nor on my FreeBSD server. It doesn't appear to be standard, so I would advise using fgets.
I'm new to C, so I apologize if the answer is obvious, I've searched elsewhere.
the libraries I'm including are:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
the code that is failing is:
char *USER = getlogin();
char CWD[128];
if (USER == NULL)
printf("cry\n");
getcwd(CWD, sizeof(CWD));
printf("this prints\n");
printf(USER);
printf("this does not\n");
printf("%s#myshell:%s> ", USER, CWD);
cry does not print, so that should mean that getlogin is successful. the segfault is caused on printf(USER);
further testing shows that the folling block prints entirely
printf("this prints\n");
printf(USER);
printf("this prints\n");
but the folling block will print this prints end then segfault without showing USER
printf("this prints\n");
printf(USER);
EDIT:
Sorry for wasting your time. I accidentally deleted an fgets that was supposed to follow it and that was causing the segfault. I've been on this bug for a couple hours now, I love it when the problem is so small.
Thanks
You should check getcwd return value. According to man page of getcwd:
If the length of the absolute pathname of the current working
directory, including the terminating null byte, exceeds size bytes,
NULL is returned, and errno is set to ERANGE; an application should
check for this error, and allocate a larger buffer if necessary.
If USER is null, printf will dereference a null pointer, which is undefined behavior. The compiler isn't required to do something that makes sense when undefined behavior occurs, so it would be allowed to not print "cry" when USER is null. You'll want to avoid undefined behavior.
Something else that might be causing your result is the fact that data sent to stdout is usually buffered. If the program crashes before the data is flushed from the buffer, the data will be lost instead of printed.
So here is how printf works...
it has to read in the format string.
it has to grab values off of the stack in order to fulfill format specifiers, format them and output them.
examples of things that could cause this...
char stringOfTest[5] = {'1','2','3','4','5'};
or
char * stringOfTest = "here are some formats that will be unsatisfied: %d%f%i%s%x";
so the first one could crash because the string isn't null terminated, and depending on the state of the application could basically read until it overruns a buffer (a good implementation should guard against this), or just happens to run into a format specifier that causes a crash... This goes for any garbage data also.
and the second one deals with how variadic functions work... all of the variables are pushed onto the stack in some order and the function doesn't have a safe way to know which the last one is... so it will keep grabbing things that are specified until it grabs something out of the stack and (maybe) crashes.
the third way is also in the second example... if you have a %s it will cause a pointer to be dereferenced... so that can also crash.
Codeblocks, C. I'm trying to write characters to a .txt file, using fwrite. The first couple of characters get written correctly, but after them the file says: _mcleanup: tos ov. I think it might be a buffer overload. Any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
FILE*p1;
p1=fopen("Tomi.txt","w+");
fseek(p1,0,SEEK_SET);
// fwrite("Toth Tamas",sizeof(char),30,p1);
while(a<10)
{
fwrite("Toth Tamas",sizeof("Toth Tamas"),1,p1);
a++;
}
return 0;
}
If I add int a = 0; immediately after FILE *p1;, the while-loop version of the program compiles without complaint, even with maximum warnings, and executes without error on my computer, even under valgrind. You want sizeof("Toth Tamas") - 1 in the fwrite call to prevent NUL bytes from being written to the file, and maybe there should be an \n after "Tamas", and see my earlier comments for other minor problems, but that code seems mostly okay.
However, the commented-out line //fwrite("Toth Tamas",sizeof(char),30,p1); does have a bug: the string constant "Toth Tamas" is only 11 bytes long (counting the terminating NUL), but you have asked fwrite to write 30 bytes, so it will access 19 more bytes beyond the end of the string, triggering undefined behavior. In context, one would expect either a segmentation fault, or garbage written to the file.
And "_mcleanup: tos ov" is 17 bytes long, so if that is (the beginning of) the next string constant in the read-only data segment of your executable, it's a plausible thing to show up as garbage written to the file, which I think is what you are saying happened.
I started learning C yesterday, so this might be a trivial question, but I still don't get this.
Let's say I have the following code:
#include <stdio.h>
#include <string.h>
int main()
{
char text[8];
strcpy(text, "Lorem ");
puts(text);
strcat(text, "ipsum!");
puts(text);
return 0;
}
This will result in a segmentation fault when (or after) concating the strings. However if I change the size of textfrom 8 to 9, it doesn't.
Please correct me if I'm wrong but this is what I thought was right:
"Lorem " - size 6 (or 7 with \0)
"ipsum!" - size 6 (or 7 with \0)
"Lorem ipsum!" - size 12 (or 13 with \0)
So, where does the 8/9 come from? Is this caused by the implementation of strcat? Or is there something like a minimum array length? Or am I making a stupid beginner's mistake?
Thanks in advance.
It's just pure luck that it didn't crash, at least on Linux I get *** stack smashing detected ***.
You are trying to append a string to another string even though the storage for the latter is insufficient. It is an example of undefined behaviour (as pointed out in the comments).
C is the sort of language that always trusts the programmer with what is in the program and so you may not even get a warning for this when compiling.
Always ensure that you have enough storage in your buffers, there are very few facilities in C that guarantee safe behaviour so do not assume things such as minimum array length.
When you overrun the end of an array, the program has undefined behaviour. this means it might do what you expect it to do or it might not. It might run as if you hadn't invoked undefined behaviour. It might crash. It might reformat your hard drive. It might print a blank page on your printer. It might do all of those things depending on when you run it.
You can't know. That's what 'undefined behaviour' is. Undefined.
I could give you an explanation for the behaviour, but it'd be unhelpful, and very hardware and implementation specific.
You can malloc to whatever size you want. and even you can realloc also according to the further input.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *text;
text = (char *) malloc(sizeof(char) * 12);
memset(text, 0x0, sizeof(char) * 12);
sprintf(text, "%s", "Lorem ");
puts(text);
sprintf(text, "%s%s", text, "ipsum!");
puts(text);
return 0;
}