I have written the following program:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void inttobusn(int val, int n, char* bus)
{
int i;
unsigned int digit;
for (i=0; i < n; i++) {
digit = pow(2, (n-1-i));
if (digit <= val) {
val -= digit;
bus[i] = '1';
//printf("hello %c",bus[i]);
} else {
bus[i] = '0';
}
}
}
main(){
char* bus;
inttobusn(37,8,bus);
int i=0;
//printf("%s",bus);
for(i=0;i<12;i++){
printf("%c",bus[i]);
}
}
But on running it doesn't print the elements of the array bus. It doesn't print anything. I am unable to figure out what is wrong. Please could someone point out?
Your code is buggy! you don't allocate memory for the bus[] array, and are trying to access values at garbage location as e.g bus[i] = 0; -- Undefined Behavior in C standard, Undefined means you can't predict how your code will behave at runtime.
This code compiled because syntax-wise the code is correct but at runtime the OS will detect illegal memory access and can terminate your code. (interesting to note: as OS detects memory right violation by a process -- An invalid access to valid memory gives: SIGSEGV And access to an invalid address gives: SIGBUS). In the worst case your program may seem execute without any failure, producing garbage results.
To simply correct it define bus array as char bus[N]; else allocated memory dynamically using void* malloc (size_t size);
Additionally, suggestion to your from #Lochemage and #Ran Eldan:
You need to declare bus with a specific size, like char bus[12]. It has to be at least large enough to fit 12 chars because your for loop at the end is iterating through that many (and you can check your code working with this suggestion #codepade).
Also there is no return type to main() in your code, its should be int main(void).
There is no memory allocated to bus so this is an undefined behavior. Either write
char bus[some sufficient size];
or use malloc, realloc to reserve memory.
You didn't initialize you bus variable.
char* bus = malloc(8 * sizeof(char));
Related
#include <stdio.h>
int main()
{
int i,a;
int* p;
p=&a;
for(i=0;i<=10;i++)
{
*(p+i)=i;
printf("%d\n",*(p+i));
}
return 0;
}
I tried to assign numbers from 0 to 10 in a sequence memory location without using an array.
You are trying to write to memory that it does not have permission to access.
The variable a is a local variable in the main function, and it is stored on the stack. The pointer p is initialized to point to the address of a. The code then attempts to write to the memory addresses starting at p and going up to p+10. However, these memory addresses are not part of the memory that has been allocated for the program to use, and so the program receives a segmentation fault when it tries to write to them.
To fix this issue, you can either change the loop condition to a smaller value, or you can allocate memory dynamically using malloc or calloc, and assign the pointer to the returned address. This will allow you to write to the allocated memory without causing a segmentation fault.
Like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
int* p = malloc(sizeof(int) * 11); // Allocate memory for 10 integers
if (p == NULL) { // Check for allocation failure
printf("Error allocating memory\n");
return 1;
}
for(i=0;i<=10;i++)
{
*(p+i)=i;
printf("%d\n",*(p+i));
}
free(p); // Free the allocated memory when you are done with it
return 0;
}
a is only an integer. not an array.
you need to declare it differently:
int i, a[10];
You can not. Memory of int is 4 bytes and you can store only single number in that memory.
for int: -2,147,483,647 to 2,147,483,647
for unsigned int: 0 to 4, 294, 967 295
There are other types you can use with different sizes, but if you want to put different numbers into one variable you need to use array.
int arr[10];
arr[0] = 0;
arr[1] = 5;
something like this.
I am just curious about how memory leaks happens when you write a C program.
Are the following are examples of memory leaks?
Trying to access the part of the memory whose access is not given to your program or when you are trying to access the location of the array which is not there.
#include <stdio.h>
int main(void)
{
int num[5];
int i;
for(i=0;i<5;i++)
scanf("%d", (num+i));
printf("%d\n", num[5]); //printing the data stored at loc num[5] which is not present.
return 0;
}
Printing the value stored in an un-initialized variables.
Use of void*memcpy(const*dst,void const*src,size_t n) function memory leak occurs when src and dst pointers points to the same memory address or function is undefined when addresses overlaps.
Use of free() more than once on the same pointers which has been freed already. For Example:
#include <stdio.h>
int main(void)
{
int*num = NULL;
int i;
num = (int*) calloc(sizeof(int), 5);
for (i = 0; i < 5; i++)
scanf("%d", (num + i));
free(num);
free(num);
return 0;
}
All of aforesaid scenarios cause undefined behavior.
printf("%d\n", num[5]); is out-of-bound memory access.
Printing the value stored in an un-initialized variables, in case of the variable has trap representation, causes UB.
Source and destination overlap in memcpy(), UB.
Multiple free() is also UB.
Also, memory leak is not about any invalid access, it is just wastage of memory leading to out of memory scenario for a system. You can read more about that here.
if is it possible run-time bad pointer exception in C language?.
I am using below compiler.
Note : Microsoft Visual C++ Compiler
Sample Programs Below.
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <Windef.h>
typedef struct tagTest{
int i;
char *str;
} Test,
FAR *LPTest,
FAR **LLPTEST;
extern LLPTEST m;
int main()
{
int i;
LLPTEST m = NULL;
m = (LLPTEST)malloc(sizeof(LLPTEST));
// Here We Check m[0] memory allocated or not ?
// example: if(m[0]), or if(m[0]->i) any other idea. here m[0] is CXX0030 error expression cannot be evaluated.
/* allocate memory */
for(i=0; i<10; i++)
{
m[i] = (LPTest) malloc(sizeof(Test));
m[i]->i = i;
m[i]->str = (char*) malloc(10*sizeof(char));
m[i]->str = "Test";
}
return 0;
}
No. C doesn't support exceptions, so there's nothing to catch. What you're seeing isn't a "bad pointer exception," it's a memory access error -- there is no way to recover from it.
You have several problems in your code. Here's a list of some of them:
Don't cast the return of malloc
For m you allocate sizeof(LLPTEST) bytes, but you should really allocate sizeof(LPTest)
Continuing the previous point, you only allocate one pointer, so only m[0] is valid, all other indexes will cause you to write out of bounds. You should do e.g.
m = malloc(sizeof(LPTest) * 10);
This point is the cause of your problems, as it causes undefined behavior
You allocate memory for m[i]->str, but then you overwrite that pointer with a pointer to a string literal, thereby loosing the pointer to the allocated memory (i.e. you have a memory leak)
Continuing the previous point, because m[i]->str now points to a string literal, and not something you allocated yourself, you can not free this pointer
No error checking, remember that malloc can fail
If you don't know how many items you need to allocate for m beforehand, you can use realloc to reallocate with a larger size.
Some exceptions can catch MSVC is to extend the syntax.
#include <windows.h>
#include <stdio.h>
typedef struct tagTest{
int i;
char *str;
} Test;
int main(){
Test *m;
//m = malloc(sizeof(Test));//it can be avoided by examining whether NULL simply.
m = NULL;//malloc is unable to allocate memory
__try{
m->i = 0;//exception occurs
m->str = "Test";
}
__except(EXCEPTION_EXECUTE_HANDLER){
if(EXCEPTION_ACCESS_VIOLATION==GetExceptionCode())
puts("ACCESS VIOLATION");
puts("EXCEPTION OCCURRED");
}
}
This question already has answers here:
I can use more memory than how much I've allocated with malloc(), why?
(17 answers)
Closed 9 years ago.
As I know that malloc allocate a specific number of bytes in the memory. However I am trying to use it and I allocate 4 bytes but it gives me NO error when I try to store more than 4 (up to 200 integers) elements in the array!! So in my code I don't need to use realloc!! I'm using Linux by the way. Finally I will pleased to hear any advice from you ... thanks in advance.
tmp.h :
#ifndef TMP_H
#define TMP_H
#define MAXLENGTH 4
#define GROWFACTOR 1.5
typedef struct stVector
{
int *vec;
int length;
int maxLength;
}Vector;
Vector newEmptyVector();
void addElement(Vector *vec, int elt);
#endif
tmp.c :
#include "stdio.h"
#include "stdlib.h"
#include "tmp.h"
Vector newEmptyVector()
{
Vector vec;
vec.vec = (int*) malloc(0);
printf("Allocating %d bytes\n", sizeof(int)*MAXLENGTH );
vec.length = 0;
vec.maxLength = MAXLENGTH;
return vec;
}
void addElement(Vector *vec, int elt)
{
/*if(vec->length == vec->maxLength)
{
vec->vec = (int*)realloc(vec->vec,sizeof(int)* vec->maxLength * GROWFACTOR);
vec->maxLength = vec->maxLength * GROWFACTOR;
}*/
vec->vec[vec->length++] = elt;
}
main.c :
#include"tmp.h"
int main(int argc, char const *argv[])
{
Vector vector = newEmptyVector();
printf("The length is %i and maxlength is ` `%i\n",vector.length,vector.maxLength);
addElement(&vector,5);
addElement(&vector,3);
addElement(&vector,1);
addElement(&vector,7);
printf("The length is %i and maxlength is ` `%i\n",vector.length,vector.maxLength);
addElement(&vector,51);
printf("The length is %i and maxlength is %i\n",vector.length,vector.maxLength);
for (int i = 0; i < 200; ++i)
{
addElement(&vector,i);
printf("The length is %i and maxlength is %i\n" ,vector.length, vector.maxLength);
}
return 0;
}
Using memory you haven't allocated invokes undefined behavior. Don't do that. In all likelyhood, Linux has give your program a page of memory, and you haven't overrun that yet. If you touch memory not allocated to your program the OS should cause your program to segfault. But it's possible that any other mallocing you do will also use parts of that page, and you'll end up corrupting your data.
Not having runtime checks for overrunning buffers is part of what makes C fast, but it puts more on the programmer not to do dumb things.
The fact that (simply because there is no bound checking in C) no error is raised does not mean that you can safely use memory outside requested bounds. You were lucky not to cause a segmentation fault, you have just fallen into a memory region that is not claimed by your malloc (let's say, it's not yours).
You can write there, but there is no guarantee that you won't be overwriting memory assigned to another malloc or, conversely, that the "extra" part will not be allocated to some other malloc. In your case, the memory region you are writing into appears not to be claimed (yet).
Regarding your specific issue:, I allocate 4 bytes but it gives me NO error when I try to store more than 4.
Keep in mind, something like:
int *anyVar = (int)malloc(0);
anyVar[0] = 12; //Will eventually invoke undefined behavior.
writing to memory you do not own will eventually invoke undefined behavior. The bad thing is that your results can seem good, and even repeatable for many runs of the code. But at some point, your code will fail.
This is how you should allocate: (by the way)
int numIntsInArray = 100;
int *anyVar = malloc(sizeof(int)*numIntsInArray);//note:do not cast output of malloc
anyVar[0] = 1;//first element of anyVar
anyVar[99] = 1000;//last element of anyVar
Do not forget to free all memory:
free(anyVar);
Other examples of undefined behavior in C & C++:
The examples of bad code below can be done, and you will likely get no compiler warnings, and may even get
expected results during run-time, but with this code, nothing is guaranteed. (exception: good examples)
char * p = "string"; // Badly formed C++11, deprecated C++98/C++03
p[0] = 'X'; // undefined behavior
Create an array instead:
char p[] = "string"; // Good
p[0] = 'X';
C++, you can create/use a standard string like this:
std::string s = "string"; // Good
s[0] = 'X';
Division by zero results in undefined behavior:
int x = 1;
return x / 0; // undefined behavior
Some pointer operations may lead to undefined behavior:
int arr[4] = {0, 1, 2, 3};
int* p = arr + 5; // undefined behavior
Leaving a non-void function without returning a value
int func(void)
{
//undefined behavior
}
Unspecified or implementation-defined behavior:
printf("%d %d\n", ++n, power(2, n)); //Bad
i = ++i + 1; //Bad
i = i + 1; // Okay
I am solving a problem on USACO. In the problem, I have to take two strings as inputs and calculate the numerical values modulo 47. If the values are same, then GO is to be printed otherwise STAY has to be printed. The initial numerical value will be calculated by taking the product of the numerical values of the alphabets ( 1 for A and similarily 26 for Z ) and then the final number will be calculated by using modulo.
My program is being compiled withour any error and running well on my computer. However, it is showing a segmentation fault as the execution error by the grader computer. The program and the output is as follows:-
Program:-
#include<stdio.h>
#include<string.h>
main()
{
int cal(char *ptr);
char *comet,*group;
int a,b;
scanf("%s",comet);
a=cal(comet);
scanf("%s",group);
b=cal(group);
if(a==b)
printf("GO");
else
printf("STAY");
return 0;
}
int cal(char *ptr)
{
int i=0,c,prod=1,mod;
while(ptr[i]!='\0')
{
if(ptr[i]>='A'&&ptr[i]<='Z')
{
c=ptr[i]-'#';
prod=prod*c;
i++;
}
}
mod=prod%47;
return mod;
}
OUTPUT:-
My question is how to pinpoint the segmentation fault. I have read about this fault but don't know what to do in this program. Any help would be great.
char *comet,*group;
int a,b;
scanf("%s",comet);
comet pointer is uninitialized. You need to allocate memory and makes comet points at this allocated memory otherwise scanf will write bytes in a random location which will likely crash your system.
Both comet and group are uninitialized pointers which do not have any memory allocated for storing the input strings.
Your program should be doing this at least. Increase the size of MAX_STRING_SIZE per your needs.
#define MAX_STRING_SIZE 100
char comet[MAX_STRING_SIZE];
char group[MAX_STRING_SIZE];
You still have the risk of buffer overflow with scanf. You can look at this post for some possible ways to avoid buffer overflow.
Your while is highly suspect: i is increased only if ptr[i] is an uppercase letter. What should happen if it isn't? How does If you have an ironclad guarantee that only uppercase letters will show up, you could write:
prod = 1;
while(*ptr) {
prod *= *ptr - 'A' + 1;
ptr++;
}
(Your ptr[i] - '#' had me scratching my head until I broke out ascii(7). I believe my version is clearer, and any halfway competent compiler will give the same code.)
Or, more idiomatically:
int cal(char *ptr)
{
int prod = 1;
while(*ptr)
prod *= *ptr++ - 'A' + 1;
return prod % 47;
}
Just be careful that the product does't overflow, perhaps do the modulus each character:
int cal(char *ptr)
{
int prod = 1;
while(*ptr) {
prod *= *ptr++ - 'A' + 1;
prod %= 47;
}
return prod;
}
You never allocate space for comet or group. Use malloc() or similar to set aside memory for those pointers, so that you can actually store something in what they point to.
#define MAX_STRING_LENGTH 256
...
char *comet, *group;
int a, b;
comet = NULL;
comet = malloc(MAX_STRING_LENGTH);
if (!comet) {
fprintf(stderr, "ERROR: Could not allocate memory to comet\n");
return EXIT_FAILURE;
}
scanf("%s",comet);
/* repeat for other pointers, as needed */
/* ... */
/* free up allocated memory at the end of the program to help prevent leaks */
free(comet);
comet = NULL;
"running well on my computer" this is not possible in your case as you are not using any compiler specific code (like getch for turbo c)
You didn't allocate memory for storing the string.The pointers comet and group don't point to anything.scanf requires an address to write the input but the pointers do not contain an address and that is why you are getting a segmentation fault.
You can allocate memory using malloc (or calloc) or you can define a character array.
The corrected code is
#include<stdio.h>
#include<string.h>
#define MAXLENGTH 100
int main()
{
int cal(char *ptr);
char comet[MAXLENGTH],group[MAXLENGTH];
int a,b;
scanf("%s",comet);
a=cal(comet);
scanf("%s",group);
b=cal(group);
if(a==b)
printf("GO");
else
printf("STAY");
return 0;
}
int cal(char *ptr)
{
int i=0,c,prod=1,mod;
while(ptr[i]!='\0')
{
if(ptr[i]>='A'&&ptr[i]<='Z')
{
c=ptr[i]-'#';
prod=prod*c;
i++;
}
}
mod=prod%47;
return mod;
}