I wrote a program in C langage. I have no problems when trying to run it with my small txt file as an argument. Unfortunately when i am trying to load much bigger file, i am getting Segmentation fault (core dumped. Even 1 line of my main function is not executed. Here is part of code responisble for starting and loading txt file as my argv[1] argument.I dont really see where is the problem.Big Txt files are about 13 MB. I am working linux(ubuntu). I would be grateful for help.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
int wage;
}Edge;
int main(int argc, char *argv[]) {
printf("Program starts");
int x,y,z;
int counter = 1;
int N,E; //node,edges
FILE *fid;
fid = fopen(argv[1],"r");
fscanf(fid,"%d%d",&N,&E);
Edge Graph[E];
int visited[N+1];
while(counter <= E){
fscanf(fid, "%d%d%d", &x, &y,&z);
Graph[counter-1].x=x;
Graph[counter-1].y=y;
Graph[counter-1].wage=z;
counter=counter+1;
}
printf("\nWe load all edges. Here is our Graph");
fclose(fid) ;
printf("Program ends");
return 0;
}
First some approximations:
With 13MB of data, your text file contains certainly over 1 million of edges (assuming that node x and y are each representend in average with 3 digits followed by a space, wage in average 1 digit followed by a space) and at least 1400 nodes.
Your variable length arrays Graph[E] and visited[N+1] are local variables, hence stored on the stack. Assuming 4 bytes per integer, that's more than 12 MB of data to put on the stack.
The amount of data that you require on the stack exceeds the usal default stack size on most linux system (8 MB).
You could consider increasing the stack size as explained in this SO question.
But you should really better consider dynamic allocaton:
Edge *Graph = calloc (sizeof(Edge),E);
int *visited = calloc (sizeof(int), N+1);
if (Graph==NULL || visited==NULL) {
printf ("Oops ! Out of memory (%d edges, %d notes) !!", E, N+1);
exit (1); // or some other kind of error handling
}
Related
I am new in C and I am used to zx basic and z80 asm. I want to use the value of an input to make a character array but
int amount_of_dice_sides ;
printf("Give number of sides of dice:\n") ;
scanf("%d", &amount_of_dice_sides) ;
char all[amount_of_dice_sides] ;
is not allowed yet
int amount_of_dice_sides=6 ;
char all[6] ;
works very fine.... how do i get that
char all[amount_of_dice_sides] ;
working?
its a very primer question, very 'basic' but i seem not to find an answer that does NOT start with 'the difference between const char*foo '
which has nothing to do with setting a char with an integer but only as a real value instead of a variable.
i found these possible 'char foo' but none is what i waht to achieve
https://medium.com/#bartobri/untangling-complex-c-declarations-9b6a0cf88c96
EDIT
i use another compiler then gcc
#include <stdio.h>
void main ()
{
int amount_of_dice_sides ;
printf("Give number of sides of dice:\n") ;
scanf("%d", &amount_of_dice_sides) ;
char all[amount_of_dice_sides] ;
return ;
}
works fine but not with zcc.
so i have to look at another place, and i am realy still learning.
see ya , and thanks for a load off immidiate answers. chris
The reason why it isn't working is that you are using a compiler and MCU from the Jurassic period. Variable-length arrays (VLA) were introduced in the C language in the year 1999. Z80 might be a nice platform to learn one flavour of assembler, but it's a horrible platform for learning C.
But regardless, you should never use VLA allocation nor heap allocation on low end microcontrollers, because they have very limited memory in general and stack memory in particular. (And heap allocation simply doesn't make sense.)
For the same reasons, you shouldn't be using stdio.h either, it will kill a significant amount of all available memory. Instead you should use the raw UART driver or write one yourself - assuming the stdio.h functions go to a terminal on a PC. Start by finding the linker map file, study it and see how much memory these libs actually take, then you'll see for yourself why they aren't suitable.
C only allows variable length stack arrays in certain situations. Specifically when you have a function, you can use a calculation based on a parameter to have a stack allocated array.
void func(int param){
int array[param] // call it here
// do some work with array as a scratch space
} // when the final curly bracket is called, the array is destroyed
However, this technique can easily get you into trouble. If you don't specify the length of an array, and a user enters a really big number, then you get a Stack Overflow. On early C compilers and platforms (like the Intel-8051), this was painfully common, as well as calling too many nested functions.
The solution is to allocate your variable length arrays on the heap. Some platforms do allow allocation to the stack as well, but not all of them.
// In sumfunc we roll a number of dice, print, and return the sum
// Malloc allocates to the heap
int sumFunc_malloc(int num_dice){
int * dice = (int*)malloc(sizeof(int) * num_dice); // our allocation
int sum = 0;
for (int i = 0; i < num_dice; i++){
dice[i] = (rand() % 6) + 1;
printf("Dice %d rolled a %d", i, dice[i];
sum += dice[i];
}
free(dice); // REQUIRED or memory will leak, and eventually program will fail
return sum;
}
// In sumfunc we roll a number of dice, print, and return the sum
// Alloca is not supported by all platforms, but is on the stack
int sumFunc_alloca(int num_dice){
int * dice = (int*)alloca(sizeof(int) * num_dice); // our allocation on the stack
int sum = 0;
for (int i = 0; i < num_dice; i++){
dice[i] = (rand() % 6) + 1;
printf("Dice %d rolled a %d", i, dice[i];
sum += dice[i];
}
return sum;
}
One final alternative, especially on devices like the 8051 is to have a scratchpad that you do large work in, and simply reusing it.
static char scratch[100];
int func(int param){
// use scratch to hold lots of temporary values
}
The best comment was explaining the WHY part: that compiling will set memory at a permanent location and if i change that size later C will get in trouble with allocated variables.
Meanwhile i do indeed learn C on a dinosar called z88dk. And it took some time befoe i was able to use it. z88dk is in a slow rewrite from 'classic' to SDCC and others aswell.
this one works in zcc but with BUILD_SCC=1 while building z88dk itself (!!!) and using a special lib for zx spectrum:
/* C source start */
/* by chris born ad 2020 as homework for z88dk, farkle */
/* zcc +zx -vn -startup=0 -clib=sdcc_iy dice_026.c -o dice026 -create-app */
#include <arch/zx.h>
#include <stdio.h>
#include <stdlib.h>
int dice(int aods)
{
char d ;
/*srand (seedrandom); */
d =+ rand()%aods ;
return d;
}
int main()
{
int x , amount_of_dice_sides , hand_of_dice ;
char number , hand[256] ;
zx_cls(PAPER_WHITE) ;
printf("Give number of sides of dice:\n") ;
scanf("%d", &amount_of_dice_sides) ;
printf("how many dice do you want:\n") ;
scanf("%d", &hand_of_dice) ;
printf(" amount of dice %d ",hand_of_dice );
if (hand_of_dice > 255)
{
hand_of_dice = 255 ;
printf(" is now %d", hand_of_dice) ;
}
printf("\n") ;
scanf("press a key") ;
/* char hand[&hand_of_dice]; */ /* int is max 65536 gives a huge hand filled with stones */
printf("You threw: \n");
for (x=1 ; x<=hand_of_dice ;x++)
{
number=dice(amount_of_dice_sides);
printf("stone %d : %d \n",x , number);
hand[x]=number;
}
printf("\n");
return 0;
}
/* C source end */
so why do i got stuck here?
well its the only source i realy have!
In this declaration,
int amount_of_dice_sides ;
printf("Give number of sides of dice:\n") ;
scanf("%d", &amount_of_dice_sides) ;
char all[amount_of_dice_sides] ;
all[amount_of_dice_sides] is a static array & it's size needs to known to compiler prior building the code.
What happens in your case is size of array is being read as input from user which happens after compilation
It's always recommended to explicitly mention the size of array to avoid memory issues in code later
I am trying to run a really simple simulation of infected nodes in a network.
The problem is that when I change the number of nodes to a big one (eg 1.000.000) the executable crashes and the results I get stop at node number 32768.
I guess that it has to do with the maximum number int datatype can store.
Is there any way to avoid this without using malloc?
I have tried to change the datatype from int to double but doesnt seem to help.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define INFECTED 1
#define HEALTHY 0
#define N 100000
int main(){
srand(time(NULL));
int infected;
int nodes[N] = { HEALTHY };
int totalinfected = 1;
int currentinfected = 1;
nodes [ rand() % N ] = INFECTED;
int timestep = 1;
FILE *ptr;
ptr = fopen ("results.csv", "w+");
while (totalinfected < N) {
for (infected = 1; infected<=currentinfected; infected++) {
int node = rand() % N;
if (nodes[node] == HEALTHY){
nodes[node] = INFECTED;
totalinfected++;
}
}
currentinfected = totalinfected;
fprintf(ptr , "%d; %d\n", timestep, totalinfected);
timestep++;
}
fclose(ptr);
printf("success all infected\n");
return 0;
}
The problem had nothing to do with the maximum number int datatype can store. (which by the way is 2,147,483,647, much larger than your value for N). And, unless you have a very small maximum stack size defined in your environment, I do not think stack size was the problem.
From running your code on my system, it appears that the range of the rand() function was really the culprit. Its range is determined by RAND_MAX, which actual value is implementation specific. In the comments, it was suggested that you check its value. On my system it is defined as:
#define RAND_MAX 32767
As a result, all progress was stopped on my system when 32767 of the 100000 array locations available were processed. The only way to move beyond this point is to have a random number generator with a range sufficient to populate all 100000 locations.
I tested this with a wonky (but in this case effective) modified number generator based on rand():
int a_bigger_rand_max(void)
{
int a, b;
a = rand();
b = rand();
return a*(RAND_MAX+1)+b;
}
Which will generate up to (RAND_MAX+1)^2-1 numbers.
Other than adding this function, and its prototype at top, this was the only line that was changed (in your main() function):
int node = rand() % N;
To:
int node = a_bigger_rand_max() % N;
This resulted in a successful run. (assuming that the criteria for success is the .csv file being populated, and a printout of success all infected\n on teh console.
Though this is strange, but I am getting a segmentation fault while scanning an integer value.
Here is my program :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int t,n,i,j;
char c;
int grid[1000][1000],right[1000][1000],down[1000][1000];
scanf("%d",&t);
printf("hello\n");
while(t--)
{
scanf("%d",&n);
memset(right, 0, sizeof(int) * 1000 *1000);
memset(down, 0, sizeof(int) * 1000 *1000);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%c",&c);
printf("CHAR = %c\n", c);
if(c == '.')
grid[i][j] = 1;
else
grid[i][j] = 0;
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d",grid[i][j]);
}
}
}
return 0;
}
Doing gdb shows segmentation fault at line scanf("%d",&t);. I cannot figure out how this is happening?
[Using gcc-4.8.4 on a linux 32-bit machine ]
The problem is that your arrays: grid, right and down are too big to fit into the stack.
As far as the reason for no compile error is concerned:
Because there is nothing wrong with this code in terms of syntax or semantics. The linker also does not have any problem.
The problem arises when the loader tries to load the program and allocate that much memory on the stack. The stack is usually 8 MB on linux systems and your arrays surpass that.
You can make them static (as suggested in the comments) as static members are allocated on the bss or data segment. But in reality you need to rethink if you need such big arrays.
Set you linker to instruct the loader to allocate a max stack segment limit that is large enough to fit your big local array.
I am not able to find prime numbers of 8 digits in spite of increasing size of array a. It is working for smaller numbers:
#include<stdio.h>
#include<math.h>
int main()
{
int n,a[100000],i,m,k;
scanf("%d",&n);
for (i=2;i<=n;i++)
a[i]=1;
m=(sqrt(n)+1);
for (i=2;i<=m;i++)
if (a[i]==1)
for (k=i*i;k<=n;k+=i)
a[k]=0;
for (i=0;i<=n;i++)
if (a[i]==1)
printf("%d\t",i);
return 0;
}
I could not get larger than 6 digits either by using the locally declared array. Such an array uses stack memory, which is in short supply compared to heap memory. The other problem is that you didn't check if the value entered for n will break the fixed size array that you declared. I solved both problems by using malloc() to allocate the exact amount of memory required, from the heap, and checked to see if the memory allocation worked.
The other small thing I tidied up was the use of \t to format the output. Once the numbers get large that will look messy. I gave a field width of 10 because that will contain an 8-digit number, also because most text terminals have a width of 80, so the numbers won't break across lines.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,i,m,k;
int *a;
scanf("%d",&n);
if ((a = malloc((n+1)*sizeof(int))) == NULL) {
printf ("Not enough memory\n");
exit (1);
}
for (i=2;i<=n;i++)
a[i]=1;
m=(sqrt(n)+1);
for (i=2;i<=m;i++)
if (a[i]==1)
for (k=i*i;k<=n;k+=i)
a[k]=0;
for (i=0;i<=n;i++)
if (a[i]==1)
printf("%10d",i);
printf("\n");
free (a);
return 0;
}
I currently have a c program that generates all possible combinations of a character string. Please note combinations, not permutations. This is the program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//Constants
static const char set[] = "abcd";
static const int setSize = sizeof(set) - 1;
void brute(char* temp, int index, int max){
//Declarations
int i;
for(i = 0; i < setSize; i++){
temp[index] = set[i];
if(index == max - 1){
printf("%s\n", temp);
}
else{
brute(temp, index + 1, max);
}
}
}
void length(int max_len){
//Declarations
char* temp = (char *) malloc(max_len + 1);
int i;
//Execute
for(i = 1; i <= max_len; i++){
memset(temp, 0, max_len + 1);
brute(temp, 0, i);
}
free(temp);
}
int main(void){
//Execute
length(2);
getchar();
return 0;
}
The maximum length of the combinations can be modified; it is currently set to 2 for demonstration purposes. Given how it's currently configured, the program outputs
a, b, c, d, aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc...
I've managed to translate this program into cuda:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//On-Device Memory
__constant__ char set_d[] = "adcd";
__constant__ int setSize_d = 4;
__device__ void brute(char* temp, int index, int max){
//Declarations
int i;
for(i = 0; i < setSize_d; i++){
temp[index] = set_d[i];
if(index == max - 1){
printf("%s\n", temp);
}
else{
brute(temp, index + 1, max);
}
}
}
__global__ void length_d(int max_len){
//Declarations
char* temp = (char *) malloc(max_len + 1);
int i;
//Execute
for(i = 1; i <= max_len; i++){
memset(temp, 0, max_len+1);
brute(temp, 0, i);
}
free(temp);
}
int main()
{
//Execute
cudaSetDevice(0);
//Launch Kernel
length_d<<<1, 1>>>(2);
cudaDeviceSynchronize();
getchar(); //Keep this console open...
return 0;
}
The cuda version of the original program is basically an exact copy of the c program (note that it is being compiled with -arch=sm_20. Therefore, printf and other host functions work in the cuda environment).
My goal is to compute combinations of a-z, A-Z, 0-9, and other characters of maximum lengths up to 10. That being the case, I want this program to run on my gpu. As it is now, it does not take advantage of parallel processing - which obviously defeats the whole purpose of writing the program in cuda. However, I'm not sure how to remove the recursive nature of the program in addition to delegating the threads to a specific index or starting point.
Any constructive input is appreciated.
Also, I get an occasional warning message on successive compiles (meaning it sporadically appears): warning : Stack size for entry function '_Z8length_di' cannot be statically determined.
I haven't pinpointed the problem yet, but I figured I would post it in case anyone identified the cause before I can. It is being compiled in visual studio 2012.
Note: I found this to be fairly interesting. As the cuda program is now, its output to the console is periodic - meaning that it prints a few dozen combinations, pauses, prints a few dozen combinations, pauses, and so forth. I also observe this behavior in its reported gpu usage - it periodically swings from 5% to 100%.
I don't think you need to use recursion for this. (I wouldn't).
Using printf from the kernel is problematic for large amounts of output; it's not really designed for that purpose. And printf from the kernel eliminates any speed benefit the GPU might have. And I assume if you're testing a large vector space like this, your goal is not to print out every combination. Even if that were your goal, printf from the kernel is not the way to go.
Another issue you will run into is storage for the entire vector space you have in mind. If you have some processing you intend to do on each vector and then you can discard it, then storage is not an issue. But storage for a vector space of length n=10 with "digits" (elements) that have k=62 or more possible values (a..z, A..Z, 0..9, etc.) will be huge. It's given by k^n, so in this example that would be 62^10 different vectors. If each digit required a byte to store it, that would be over 7 trillion gigabytes. So this pretty much dictates that storage of the entire vector space is out of the question. Whatever work you're going to do, you're going to have to do it on the fly.
Given the above discussion, this answer should have pretty much everything that you need. The vector digits are handled as unsigned int, you can create whatever mapping you want between unsigned int and your "digits" (i.e. a..z, A..Z, 0..9, etc.) In that example, the function that was performed on each vector was testing if the sum of the digits matched a certain value, so you could replace this line in the kernel:
if (vec_sum(vec, n) == sum) atomicAdd(count, 1UL);
with whatever function and processing you wanted to apply to each vector generated. You could even put a printf here, but for larger spaces the output will be fragmented and incomplete.