Segmentation fault (core dumped) and zlib - c

I am very new to both using Linux and creating anything remotely serious on C. I've been trying to create a program which will simply compress a single string, but I keep getting this Segmentation fault when trying to run the compiled file.
I compiled it using:
gcc 2.c -o test.o -lz
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include <assert.h>
int main ()
{
char *istream = malloc(10), *ostream = malloc(120);
istream = "istream";
int res = compress(ostream, (uLongf *)strlen(ostream), istream,(ulong)strlen(istream));
return 0;
}
Could anyone explain to me why this error is happening and how can I improve my code?

This line would appear to be the main problem:
(uLongf*)strlen(ostream)
You are interpreting a size_t value as a pointer to a buffer. You are meant to pass the address of an unsigned long containing the length of the output buffer. Take another look at the documentation for compress.
On top of that you don't yet understand how C strings work. The assignment operator when used with a char* lvalue merely copies an address and not the contents of a string. I suggest that you declare your buffers like this:
const char *istream = "istream";
char ostream[120];
I think your program should be something along these lines:
int main(void)
{
const char *istream = "istream";
char ostream[120];
uLongf destLen = sizeof(ostream);
int res = compress((Bytef*)ostream, &destLen, (Bytef*)istream, strlen(istream));
return 0;
}
Note that I wrote the code assuming that you are using a C compiler. And hence int main(void).

First you make istream point to memory you allocate:
char *istream = malloc(10)
then you make it point to a literal (and therefore constant and read-only) string:
istream = "istream";
You need to copy the string literal into the allocated memory, or you will no longer have the original pointer you allocated and have a memory leak. You also will not be able to free that pointer, since istream points to something you haven't allocated with malloc.
As for the crash, see the answer by David Heffernan.
As a side-note, there is no C++ in your code, only pure and plain C.

Change:
istream = "istream"
To
strcpy(istream,"istream");
In addition, what did you expect strlen(ostream) to return? 120?
strlen returns the index of the first 0 character encountered within the input string.
In your case, the contents of the memory pointed by ostream is unknown (i.e. "junk").
strlen will scan this memory until a 0 character is encountered, but will probably exceed the 120-byte memory space and cause a memory access violation.
Change strlen(ostream) to 120 if that was your intention.

Related

Understanding malloc with char pointers and strcpy

I want to write a simple program and I want it to fail to understand strcpy and proper memory management but it still executes. I am trying to dynamically allocate memory (with malloc) for a string enough for only 3 (or anything less than the source) chars to be used as the destination and allocate less memory (or chars) than the string array of the source which is allocated on the stack (string of 10 chars). It copies and prints the content no matter how I define the memory allocation. what's the mistake here?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *ch = NULL;
char name[10] = "something";
ch = (char*)malloc(3 * sizeof(char));
strcpy(ch, name);
printf("%s\n", name);
free(ch);
ch = NULL;
}
The behaviour of writing array out of bounds is undefined. On my computer, without optimization:
% gcc overflow.c
% ./a.out
something
and with optimization enabled
% gcc -O3 overflow.c
In file included from /usr/include/string.h:495,
from overflow.c:2:
In function ‘strcpy’,
inlined from ‘main’ at overflow.c:10:5:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:90:10: warning:
‘__builtin___memcpy_chk’ writing 10 bytes into a region of size 3
overflows the destination [-Wstringop-overflow=]
90 | return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% ./a.out
*** buffer overflow detected ***: terminated
[2] 240741 abort (core dumped) ./a.out
The reason is that with optimization GCC will actually propagate the array sizes and will produce machine code equivalent to
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char name[10] = "something";
char *ch = malloc(3);
__memcpy_chk(ch, name, sizeof name, 3);
puts(name);
free(ch);
}
and __memcpy_chk will check the length of the destination buffer, and since it is exceeded, the program will abort at runtime.
Always when developing, remember to test your code optimizations enabled too!
The mistake here is you're relying on undefined behaviour.
Compiler does not throw any error for out-of-bound (or invalid) memory access, but when your program try to access an invalid memory, the behaviour is undefined.
For strcpy(), in case the destination buffer is not large enough to hold the content from the source, including the null-terminator, then essentially you'll be accessing memory out of bound, which is invalid, causing the undefined behaviour. It's the responsibility of the programmer to ensure the destination buffer has enough space to store the string to be copied.
From the man page
The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest. The strings may not overlap, and the destination string dest must be large enough to receive the copy.[....]

the function of malloc(using malloc correctly)

so I'm quite new in this, sorry if it sound like a dumb question
I'm trying to understand malloc, and create a very simple program which will print "ABC" using ASCII code
here is my code (what our professor taught us) so far
char *i;
i = malloc(sizeof(char)*4);
*i = 65;
*(i+1) = 66;
*(i+2) = 67;
*(i+3) = '\0';
what I don't understand is, why do I have to put malloc there?
the professor told us the program won't run without the malloc,
but when I tried and run it without the malloc, the program run just fine.
so what's the function of malloc there?
am I even using it right?
any help and or explanation would be really appreciated
the professor told us the program won't run without the malloc
This is not quite true, the correct wording would be: "The program's behavior is undefined without malloc()".
The reason for this is that
char *i;
just declares a pointer to a char, but there's no initialization -- this pointer points to some indeterminate location. You could be just lucky in that writing values to this "random" location works and won't result in a crash. I'd personally call it unlucky because this hides a bug in your program. undefined behavior just means anything can happen, including a "correct" program execution.
malloc() will dynamically request some usable memory and return a pointer to that memory, so after the malloc(), you know i points to 4 bytes of memory you can use. If malloc() fails for some reason (no more memory available), it returns NULL -- your program should test for it before writing to *i.
All that said, of course the program CAN work without malloc(). You could just write
char i[4];
and i would be a local variable with room for 4 characters.
Final side note: sizeof(char) is defined to be 1, so you can just write i = malloc(4);.
Unfortunately, "runs fine" criterion proves nothing about a C program. Great deal of C programs that run to completion have undefined behavior, which does not happen to manifest itself on your particular platform.
You need special tools to see this error. For example, you can run your code through valgrind, and see it access uninitialized pointer.
As for the malloc, you do not have to use dynamic buffer in your code. It would be perfectly fine to allocate the buffer in automatic memory, like this:
char buf[4], *i = buf;
You have to allocate space for memory. In the example below, I did not allocate for memory for i, which resulted in a segmentation fault (you are trying to access memory that you don't have access to)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *i;
strcpy(i, "hello");
printf("%s\n", i);
return (0);
}
Output: Segmentation fault (core dumped)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *i;
/*Allocated 6 spots with sizeof char +1 for \0 character*/
i = malloc(sizeof(char) * 6);
strcpy(i, "hello");
printf("%s\n", i);
return (0);
}
Result: hello
Malloc allows you to create space, so you can write to a spot in memory. In the first example, "It won't work without malloc" because i is pointing to a spot in memory that doesn't have space allocated yet.

Do i must malloc a returned string inside a function? [duplicate]

This question already has answers here:
String literals: Where do they go?
(8 answers)
Closed 9 years ago.
The following program will print on the screen "Hello\nWorld\n" ('\n' = line down) as it supposed to. But actually, as i learned, something here isn't done as it should be. The "hello" and "world" strings are defined inside a function (and therefore are local and their memory is released at the end of the function's scope - right?). Actually we don't do a malloc for them as we are supposed to (to save the memory after the scope). So when a() is done, isn't the memory stack move up it's cursor and "world" will be placed in the memory at the same place where "hello" was ? (it looks like it doesn't happen here and I don't understand why, and therefore, why do i usually need to do this malloc if actually the memory block is saved and not returned after the scope?)
Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *a()
{
char *str1 = "Hello";
return str1;
}
char *b()
{
char *str2 = "World";
return str2;
}
int main()
{
char *main_str1 = a();
char *main_str2 = b();
puts(main_str1);
puts(main_str2);
return 0;
}
edit: So what you are saying actually is that my "hello" string takes a constant place in memory and even though it's inside a function , i can read it from anywhere i want if i have it's address (so its defined just like a malloc but you cant free it) - right ?
Constant strings are not allocated on the stack. Only the pointer is allocated on the stack. The pointer returned from a() and b() points to some literal constant part of executable memory.
Another question dealing with this topic
In this case all works because string literal are allocated in memory data available for all program lifetime.
Your code is equivalent to (produce same result,I mean):
char *a()
{
return "Hello";
}
This code doesn't work
char* a()
{
char array[6];
strcpy(array,"Hello");
return array;
}
because array[] is created on stack and destroyed when function returning
String literals (strings that are defined with "quotes") are created statically in the program's memory space at compile-time. When you go char *str1 = "Hello";, you aren't creating new memory at run-time like you would with a malloc call.
C does not obligate the compiler to move memory on the stack as OP suggests and that is why the observed behavior is not failing as expected.
Compiler models and optimizations may allow a program, such as OP's with undefined behavior (UB), to apparently work without side effects like corrupt memory or seg faults. Another compiler may also compile the same code with very different results.
Version with allocated memory follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *a() {
return strdup("Hello"); // combo strlen, malloc and memcpy
}
char *b() {
return strdup("World");
}
int main() {
char *main_str1 = a();
char *main_str2 = b();
puts(main_str1);
puts(main_str2);
free(main_str1);
free(main_str2);
return 0;
}

How do I transfer text between different functions in C?

I have two .c files that I would like to compile into on executable. Having just started learning C, I'm finding it tricky to know how to transfer text as an argument between functions (which I've found to be incredibly simple in every other language).
Here are the two files:
Program.c
#include <stdio.h>
#include <string.h>
int main(){
char temp[40] = stringCall();
printf("%s",temp);
}
StringReturn.c
#include <stdio.h>
#include <string.h>
char[] stringCall(){
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
}
I usually get a problem that says something like "Segmentation Failed (core dumped)" or alike. I've done a lot of Googling and amazing I can't really find a solution, and certainly no simple tutorial "This is how to move text between functions".
Any help would be appreciated :)
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
This is invalid, you're returning an auto array which gets out of scope after the function returns - this invokes undefined behavior. Try returning the string literal itself (it's valid throughout the program):
return "Hello, Stack Overflow!";
Or a dynamic duplicate of your array:
char toReturn[40] = "Hello, Stack Overflow!";
return strdup(toReturn);
In this latter case, you'll need to free() the string in the caller function.
You are correct, this isn't simple in C because C can't treat strings as values.
The most flexible way to do it is this:
// Program.c
char temp[40];
if (stringCall(temp, sizeof temp) <= sizeof temp) {
puts(temp);
} else {
// error-handling
puts("My buffer wasn't big enough");
}
// StringReturn.c
int stringCall(char *buf, int size) {
const char toReturn[] = "Hello, Stack Overflow!";
if (sizeof toReturn <= size) {
strcpy(buf, toReturn);
}
return sizeof toReturn;
}
stringCall doesn't return the string data, it writes it to a buffer supplied by the caller
A buffer always comes with a size. You could use size_t or ssize_t for this rather than int.
stringCall checks the size before writing. There are other ways to do this in a single call, all of which are either not in C89 and C99, or are defective in some other way. C11 introduces strcpy_s. Use what tools you can, which should be logically equivalent to checking it yourself as in my code above. Never forget to make sure there's space for the nul terminator, which invisibly lurks at the end of every C string.
stringCall returns the number of bytes that it wants to write, even if it doesn't write anything. This means that a caller whose buffer is too small can allocate a bigger one and try again. For that matter a caller can do stringCall(NULL, 0) to get the size without trying any particular buffer.
I'm using sizeof here because I'm using arrays whose size is known by the compiler, but in practice stringCall might use strlen or some other way of knowing how much data it wants to write.
As I've written it, callers are required not to pass in a negative value for size. That's usually OK, because their buffer in point of fact cannot have a negative size, so their code is already buggy if they do. But if you want to be really sure, or if you want to help your callers catch those bugs, you could write if ((int) sizeof toReturn < size) or if (size > 0 && sizeof toReturn < size).
"Most flexible" isn't always best, but this is good when the function is actually generating the text on the fly, especially when there isn't an easy way for the caller to know the length in advance without doing half the work that stringCall is supposed to do for them. The interface is similar to the C99 standard function snprintf.

C Pointers question

I have a small conceptual question about pointers. This may be embarrassing but I need to know the answer.
I was trying to read a line from a file using getline function. getline takes char ** as its first argument and that is where the line pointer is stored. Please see the pasted code below and tell me the difference between them. Notice the declaration and use of readLine pointer.
The second code gave me segmentation fault when it reached printf(). I checked the value at *readLine with gdb(before printf()) and it was correct, but when it goes to printf(), boom SIGSEGV
this code works:
FILE *fp;
char *readLine;
readLine=NULL;
int s=0;
while(getline(&readLine,(size_t *)&s,fp) != -1){
printf("%s\n",readLine);
}
this code does not work:
FILE *fp;
char **readLine;
*readLine=NULL;
int s=0;
while(getline(readLine,(size_t *)&s,fp) != -1){
printf("%s\n",*readLine);
}
cheers...
rv
(size_t *)&s
This will crash a 64-bit machine with 32-bit ints. The solution to this kind of problem is to declare the type which is required (size_t s;), not to cast anything. In x86-64, this assigns 8 bytes to a 4-byte location on the stack, which results in stack corruption. Because the overwrite happens in the called function, it could overwrite the return address, for example.
char **readLine;
*readLine=NULL;
This is also an instant crash. You are assigning a value to the target of an uninitialized pointer, changing the bytes at some unknown point in memory.
In the first case, the variable readLine -- the value of which is stored on the stack, in it's own special reserved area -- is a pointer-to-char. When you pass its address to getline(), you tell getline() to store the real pointer into the memory which is reserved for it. Everything works.
In the second case, readLine is a pointer-to-pointer-to-char, and again, there is space reserved for it on the stack. When you call getline(), though, you're telling getline() that the readLine variable holds the address in which the pointer-to-char should be stored. But readLine points to some random memory somewhere, not to a location which getline() should be allowed to store data. In fact, you've already started corrupting memory when you write
*readLine = NULL;
because as I said, readLine is pointing to memory you don't own. getline() just makes it worse.
Please find example bellow, it is compiled end executed on Ubuntu 18.04.
If you use linux, please type "man getline", man pages are your friend.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
char *readLine;
FILE *fp;
size_t n = 0;
readLine=NULL;
fp = fopen("example.c", "r");
while(getline(&readLine,&n,fp) != EOF){
printf("%s\n",readLine);
}
free(readLine);
}

Resources