char** : Parse the entire memory properly - c

Im am trying to get some words from a txt file and store them into a char** . Although I think my array allocates corectly room for 100 words , my last one fails to be printed in a human-readable way.Also,if you look carefully there are 4 characters that are being printed (so this indicates that the correct size of memory refers to the lenght of the word,which is 4). Can you please point out for what am I missing ? I am running in linux Ubuntu 20.04 (VirtualBox).
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <fcntl.h>
#define N 100
#define STRLIM 60
char** cat;
int fd;
int main(int argc, char const *argv[])
{ int i;
cat=(char**)malloc(sizeof(char)*N);
fd=open("dictionary.txt",O_RDONLY);
if(fd==-1){
printf("fd error %d" , fd);
perror("Error:");
}
for(i=0;i<N;i++){
cat[i]=(char*)malloc(sizeof(char)*STRLIM);
read(fd,cat[i],40);
printf("%s", cat[i]);
}
printf("the value of i is: %d",i);
return 0;
}//end of main
PS: I am getting a warning that which goes like this :
v1.c:25:9: warning: implicit declaration of function ‘read’; did you mean ‘fread’? [-Wimplicit-function-declaration]
Is it really necessary for "read" to have an unsigned int as a third arguement?
The words of the "dictionary.txt" are these (there a hundred words down bellow) :
shocking
boundary
post
dapper
zoom
bashful
damaging
sore
unadvised
fresh
birthday
wrathful
hook
nose
wonder
doubt
important
synonymous
bell
dare
selective
raspy
unused
heavy
wiggly
land
coal
humorous
humdrum
plausible
languid
depressed
imminent
helpless
parsimonious
verse
deep
tricky
window
sedate
torpid
earsplitting
protect
breath
drawer
pear
bomb
drum
can
superficial
crook
stimulating
majestic
innocent
steep
robin
weak
tumble
geese
bulb
channel
frantic
obtain
shave
nerve
boiling
picture
sand
measly
tasteful
steadfast
hallowed
rabid
fax
aspiring
utter
wave
confused
zephyr
absent
lamentable
idea
oatmeal
comfortable
cars
reduce
colossal
heat
lettuce
simple
homeless
decision
cellar
ruthless
time
railway
possible
silly
chance
food

Sorry, wasn't able to add a comment...
you won't get a warning if you include unistd.h.
I don't know why you want to use the malloc function in this code (maybe for another part of the code).
It is better to have a buffer and do something like this:
char buffer[STRLIM];
int x;
while ((x = read(fd, buffer, STRLIM)) > 0) {
write(1, buffer, x);
}
where x is the number of bytes that the read function was able to read from the file, and then we write x bytes to the output.

Related

Strange output when using system("clear") command in C program

I have the following code
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#define dimensions 5
int RandomNumInRange(int M, int N)
{
return M + rand() / (RAND_MAX / (N - M + 1) + 1);
}
char ** CreateWorld(int dim)
{
int i,j;
char **world = malloc(dim *sizeof(char*));
for(i=0;i<dim;i++)
world[i]=malloc(dim*sizeof(char));
for(i=0;i<dim;i++)
for(j=0;j<dim;j++)
world[i][j]=42;
return world;
}
void CreateCastle(char **world)
{
//assuming world is big enough
//to hold a match of 2
int randRow,randCol;
//1 to dimension -2 so we can spawn a 3x3 castle
randRow = RandomNumInRange(1,dimensions-2);
randCol = RandomNumInRange(1,dimensions-2);
printf("position: %d %d\n", randRow, randCol);
world[randRow][randCol]='c';
//fill the rest so castle is 3x3
//assuming there is enough space for that
world[randRow-1][randCol-1]=35;
world[randRow-1][randCol]=35;
world[randRow-1][randCol+1]=35;
world[randRow][randCol-1]=35;
world[randRow][randCol+1]=35;
world[randRow+1][randCol-1]=35;
world[randRow+1][randCol]=35;
world[randRow+1][randCol+1]=35;
}
void DisplayWorld(char** world)
{
int i,j;
for(i=0;i<dimensions;i++)
{
for(j=0;j<dimensions;j++)
{
printf("%c",world[i][j]);
}
printf("\n");
}
}
int main(void){
system("clear");
int i,j;
srand (time(NULL));
char **world = CreateWorld(dimensions);
DisplayWorld(world);
CreateCastle(world);
printf("Castle Positions:\n");
DisplayWorld(world);
//free allocated memory
free(world);
//3 star strats
char ***world1 = malloc(3 *sizeof(char**));
for(i=0;i<3;i++)
world1[i]=malloc(3*sizeof(char*));
for(i=0;i<3;i++)
for(j=0;j<3;j++)
world1[i][j]="\u254B";
for(i=0;i<3;i++){
for(j=0;j<3;j++)
printf("%s",world1[i][j]);
puts("");
}
free(world1);
//end
return 0 ;
}
If I use the system("clear") command, I get a line consisting of "[3;J"
followed by an expected output. If I run the program again, I get the same gibberish, then many blank newlines, then the expected output. If I put the system("clear") command in comments then both the "[3;J" and the blank newlines don't show and the output is expected.
Edit: it seems the error is not in the code, but rather in the way the terminal on my system is (not) set. Thank you all for your input, I definitely have a lot of interesting stuff to read and learn now.
The codes being sent by your clear command from don't seem to be compatible with the Gnome terminal emulator, which I believe is what you would be using.
The normal control codes to clear a console are CSI H CSI J. (CSI is the Control Sequence Initializer: an escape character \033 followed by a [). CSI H sends the cursor to the home position, and CSI J clears from the cursor position to the end of the screen. You could also use CSI 2 J which clears the entire screen.
On Linux consoles and some terminal emulators, you can use CSI 3 J to clear both the entire screen and the scrollback. I would consider it unfriendly to do this (and the clear command installed on my system doesn't.)
CSI sequences can typically contain semicolons to separate numeric arguments. However, the J command doesn't accept more than one numeric argument and the semicolon seems to cause Gnome terminal to fail to recognize the control sequence. In any event, I don't believe Gnome terminal supports CSI 3 J.
The clear command normally uses the terminfo database to find the correct control sequences for the terminal. It identifies the terminal by using the value of the TERM environment variable, which suggests that you have to wrong value for that variable. Try setting export TERM=xterm and see if you get different results. If that works, you'll have to figure out where Linux Mint configures environment variables and fix it.
On the whole, you shouldn't need to use system("clear") to clear your screen; it's entirely too much overhead for such a simple task. You would be better off using tputs from the ncurses package. However, that also uses the terminfo database, so you will have to fix your TERM setting in any case.

Context switching - Is makecontext and swapcontext working here (OSX)

I'm having some fun with context switching. I've copied the example code into a file
http://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html
and i defined the macro _XOPEN_SOURCE for OSX.
#define _XOPEN_SOURCE
#include <stdio.h>
#include <ucontext.h>
static ucontext_t ctx[3];
static void
f1 (void)
{
puts("start f1");
swapcontext(&ctx[1], &ctx[2]);
puts("finish f1");
}
static void
f2 (void)
{
puts("start f2");
swapcontext(&ctx[2], &ctx[1]);
puts("finish f2");
}
int
main (void)
{
char st1[8192];
char st2[8192];
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 0);
getcontext(&ctx[2]);
ctx[2].uc_stack.ss_sp = st2;
ctx[2].uc_stack.ss_size = sizeof st2;
ctx[2].uc_link = &ctx[1];
makecontext(&ctx[2], f2, 0);
swapcontext(&ctx[0], &ctx[2]);
return 0;
}
I build it
gcc -o context context.c -g
winges at me about get, make, swap context being deprecated. Meh.
When I run it it just hangs. It doesn't seem to crash. It just hangs.
I tried using gdb, but once I step into the swapcontext, it just is blank. It doesn't jump into f1. I just keep hitting enter and it will just move the cursor into a new line on the console?
Any idea what's a happening? Something to do with working on the Mac/deprecate methods?
Thanks
It looks like your code is just copy/pasted from the ucontext documentation, which must make it frustrating that it's not working...
As far as I can tell, your stacks are just too small. I couldn't get it to work with any less than 32KiB for your stacks.
Try making these changes:
#define STACK_SIZE (1<<15) // 32KiB
// . . .
char st1[STACK_SIZE];
char st2[STACK_SIZE];
yup fixed it. why did it fix it though?
Well, let's dig into the problem a bit more. First, let's find out what's actually going on.
When I run it it just hangs. It doesn't seem to crash. It just hangs.
If you use some debugger-fu (be sure to use lldb—gdb just doesn't work right on os x), then you will find that when the app is "hanging", it's actually spinning in a weird loop in your main function, illustrated by the arrow in the comments below.
int
main (void)
{
char st1[8192];
char st2[8192];
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 0);
getcontext(&ctx[2]);// <---------------------+ back to here
ctx[2].uc_stack.ss_sp = st2;// |
ctx[2].uc_stack.ss_size = sizeof st2;// |
ctx[2].uc_link = &ctx[1];// |
makecontext(&ctx[2], f2, 0); // |
// |
puts("about to swap...");// |
// |
swapcontext(&ctx[0], &ctx[2]);// ------------+ jumps from here
return 0;
}
Note that I added an extra puts call above in the middle of the loop. If you add that line and compile/run again, then instead of the program just hanging you'll see it start spewing out the string "about to swap..." ad infinitum.
Obviously something screwy is going on based on the given stack size, so let's just look for everywhere that ss_size is referenced...
(Note: The authoritative source code for the Apple ucontext implementation is at https://opensource.apple.com/source/, but there's a GitHub mirror that I'll use since it's nicer for searching and linking.)
If we take a look at makecontext.c, we see something like this:
if (ucp->uc_stack.ss_size < MINSIGSTKSZ) {
// fail without an error code since makecontext is a void function
return;
}
Well, that's nice! What is MINSIGSTKSZ? Well, let's take a look in signal.h:
#define MINSIGSTKSZ 32768 /* (32K)minimum allowable stack */
#define SIGSTKSZ 131072 /* (128K)recommended stack size */
Apparently these values are actually part of the POSIX standard. Although I don't see anything in the ucontext documentation that references these values, I guess it's kind of implied since ucontext preserves the current signal mask.
Anyway, this explains the screwy behavior we're seeing. Since the makecontext call is failing due to the stack size being too small, the call to getcontext(&ctx[2]) is what is setting up the contents of ctx[2], so the call to swapcontext(&ctx[0], &ctx[2]) just ends up swapping back to that line again, creating the infinite loop...
Interestingly, MINSIGSTKSZ is 32768 bytes on os x, but only 2048 bytes on my linux box, which explains why it worked on linux but not os x.
Based on all of that, it looks like a safer option is use the recommended stack size from sys/signal.h:
char st1[SIGSTKSZ];
char st2[SIGSTKSZ];
That, or switch to something that isn't deprecated. You might take a look at Boost.Context if you're not averse to C++.

Memory problems with C

Hello and have a good day, I've come here after days of trial and error so forgive me if I'm beign silly.
I have the following code. The idea of this code is first of all read all the files I have and store all the data into a matrix NsitesxNxxNy and then use the data for other unrelated things.
The amount of data is not very much, I mean i have 800 files of data which occupe no more than 80MB but anyway if I try to use a number for DataFiles higher than 134 I get a Segmentation Fault error.
I think it's weird because if it works with a number of DataFiles=100 why it should'nt work for higher?
I thought it was because for a reason my program does not get enough memory allocated for the process or because I'm having an issue when allocating the memory. But I always have the same amount of data and my data files have exactly 88*44 values and working only until 134 files it's... I don't have experience with "high amount" of data/memory usage but I think that 1000*88*44 which is about 10^6 double digits it's not too much.
I'm using GCC compiler and Ubuntu (14.02 I think), when I try to compile and execute this program in Windows using Codeblocks it just crashes (another mistery).
Oh I also had a terminal open with RAM memory usage and with 134 files it was nothing big to handle for the computer.
EDIT: I also tried making several [100][Nx][Ny] arrays and use them one by one but that also lead to the Segmentation Fault error.
EDIT2: minor erratas text and code
Also, I'm following this way because I need all that data simultaneously... I'm thinking of new ways of avoiding this but last couple days did'nt find any alternative.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
const int Nx=88; //
const int Ny=44; //
const int DataFiles=100; // How many data files are we going to read
int main() {
int i, j, ki , kj ,index;
double fun[DataFiles][Nx][Ny], Res[DataFiles][Nx][Ny],mean[Nx][Ny];
FILE * conf;
char file[100];
for (index=0; index<DataFiles; index++){
sprintf(file,"data//file%i00.txt",5000+index*25);
conf=fopen(file,"r");
for(ki=0;ki<Nx;ki++){
for(kj=0;kj<Ny;kj++){
fscanf(conf,"%i %i %lf", &i, &j, &fun[index][ki][kj]);
mean[ki][kj] = mean[ki][kj] + fun[index][ki][kj] ;
}}
fclose (conf);
}
// do things with my loaded data
}
You ran out of stack. Generally speaking, don't allocate more than 8k at once on the stack. Oops.
Change
double fun[DataFiles][Nx][Ny], Res[DataFiles][Nx][Ny],mean[Nx][Ny];
To
double (*fun)[Nx][Ny] = malloc(sizeof(fun[0]) * DataFiles), (*Res)[Nx][Ny] = malloc(sizeof(Res[0]) * DataFiles), mean[Nx][Ny];
if (!fun || !Res) {
/* handle OOM */
}

Trouble with populating student's marks

This is in response to a similar threat I posted the other day with reading a file into the requisite data structure with the file data like so, I can't remember who said it but yes there's four subjects. (I wanted to post an overall reply to all responses but could only comment on each post made):
131782 Mathematics 59
075160 Mathematics 92
580313 Physics 63
073241 Mathematics 32
487476 Mathematics 73
075160 Physics 98
472832 English 44
...
I'm using fscanf() now to parse the data and this is a much better approach. I made another thread yesterday about removing duplicate strings. I've scrapped that idea now and just used qsort on the student IDs and created a for loop that skips every four elements and rings the unique student IDs into the structure. I did a printf() command earlier and they're successfully stored. Now I've got the IDs stored I'm now ready to search for that ID and populate their marks and I "think" it's almost there except for a slight problem inside the update_student() function.
If you look at my code, or even compile it, it's not liking the line that's supposed to populate the mark for the student, student_data[idx].marks[buffer_subjects]=marks. But buffer_subjects is a string but if you look at my defines those strings are constants which is the whole idea when it gets to this stage.
How can I fix this?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STUDENTS 20
#define COMPUTING 0
#define ENGLISH 1
#define MATHEMATICS 2
#define PHYSICS 3
#define SUBJECTS 4
#define ROWS 80
#define SIZE 100
int string_compare(void const *x, void const *y)
{
return strcmp(*(char**)x, *(char**)y);
}
struct student
{
char student_ID[SIZE];
int marks[SUBJECTS];
};struct student student_data[STUDENTS];
int find_student(char buffer_IDs[])
{
int j;
for(j=0;j<STUDENTS;j++)
if(strcmp(student_data[j].student_ID,buffer_IDs)==0)
return j;
}
void update_student(char buffer_IDs[], char buffer_subjects[], int marks[])
{
int idx = find_student(buffer_IDs);
student_data[idx].marks[buffer_subjects] = marks;
}
int main(void)
{
FILE *input;
int i,j, data_items;
char buffer_IDs[ROWS][SIZE];
char buffer_subject[ROWS][SIZE];
int marks[ROWS][SIZE];
char *string_ptrs[ROWS];
if((input=fopen("C:\\marks\\marks.txt","r"))==NULL)
perror("File open failed!");
else
{
for(i=0;i<ROWS;i++)
{
while((data_items=fscanf(input, "%s %s %d", buffer_IDs[i], buffer_subject[i], marks[i])!=3));
printf("%s %s %d\n", buffer_IDs[i], buffer_subject[i], *marks[i]);
string_ptrs[i]=buffer_IDs[i];
}
putchar('\n');
qsort(string_ptrs, sizeof(string_ptrs)/sizeof(char*), sizeof(char*), string_compare);
for(i=0;i<ROWS;i=i+4)
{
j=0;
strcpy(student_data[j].student_ID,string_ptrs[i]);
printf("%s\n",student_data[j].student_ID);
j++;
}
for(i=0;i<ROWS;i++)
update_student(buffer_IDs[i], buffer_subject[i], marks[i]);
}
return 0;
}
> Blockquote
There are numerous failures in this block of code. I would seriously recommend building it up block by block, and using a debugger to confirm that the data in each stage is as expected, and not proceeding till each of the lower level blocks work (and do not produce compile errors).
Running it through GDB with some sample data suggests problems even at the point of reading in and parsing data from the file on disk.
We can assist with individual issues as they arise from this approach.

libopcodes: get the size of a instruction

I have to find out the size of a instruction which I have in memory (actually, I have a small code segment in memory and want to get the size of the first instruction).
It took me some time to find libopcodes and libbfd. I red the headers and tried to come up with a simple solution but it seems like I missunderstood something since the program always crashes:
int main(int argc, char **argv) {
disassemble_info *dis = malloc(sizeof(*dis));
assert(dis != NULL);
dis->arch = bfd_arch_i386;
dis->read_memory_func = buffer_read_memory;
dis->buffer_length = 64;
dis->buffer = malloc(dis->buffer_length);
memset(dis->buffer, 0x90, dis->buffer_length);
disassemble_init_for_target(dis);
int instr_size = print_insn_i386(0, dis);
printf("instruction size is %d\n", instr_size);
return 0;
}
The expected result would be an instruction size of 1 (nop).
EDIT:
sorry guys, I'm a stupid person.
memset(dis, 0, sizeof(*dis));
There is some code in the Linux kernel you can steal. It should work well if copied into a user mode program.
Take a look at arch/x86/lib and arch/x86/tools
There's an opcode map file there, and an awk script that reads it to produce a table in a file named innat.c. There are some other files there that use the table to implement a decoder.
It is sufficient to determine instruction sizes.
This assumes you are ok with GPL, of course.
It looks like the disassemble_info data structure requires more initialization than you have provided. From examples I have been studying, the correct way to initialize is to call init_disassemble_info().
See if that helps. Failing that, compile your program with debug info ('-g') and run gdb to diagnose where the crash occurs.

Resources