I got a struct Chat
struct Chat
{
int m_FD;
int m_BindPort;
char m_NameLength;
char* m_Name;
char m_PeerCount;
char** m_PeerList;
} typedef Chat_t;
i'm initializing it with this function:
int chat_init(Chat_t* this, unsigned int nameLen, char* name, unsigned short int bindPort, unsigned int peerCount, char** peerList)
{
this->m_NameLength = nameLen;
this->m_Name = malloc(sizeof(char) * (nameLen+1));
strcpy(this->m_Name, name);
this->m_BindPort = bindPort;
this->m_PeerCount = peerCount;
this->m_PeerList = malloc(sizeof(char*) * peerCount);
for(int i=0; i<peerCount; i++)
{
this->m_PeerList[i] = malloc(sizeof(char) * 16); // enough for xxx.xxx.xxx.xxx\0
strcpy(this->m_PeerList[i], peerList[i]);
}
//Socket initialization for TCP connection...
//Commenting this out doesn't change anything so i'm hiding it for simplification
return 0;
}
After that i'm calling a second function
int chat_communicate(Chat_t* this)
{
printf("2\n");
fflush(stdout);
//Some stuff that doesn't matter because it isn't even called
return retVar;
}
in main like this
void main(void)
{
char* peerList[1];
char username[USERNAME_MAX_LEN];
int initRet;
int loopRet;
Chat_t chat;
peerList[0] = "192.168.2.2";
memset(username, 0, USERNAME_MAX_LEN);
printf("Please enter your user name: ");
scanf("%s", username);
username[USERNAME_MAX_LEN-1] = 0;
initRet = chat_init(&chat, strlen(username), username, 1234, 1, peerList);
printf("File Descriptor: %d\n", chat.m_FD);
printf("Binding Port: %d\n", chat.m_BindPort);
printf("Name Length: %d\n", chat.m_NameLength);
printf("Name: %s\n", chat.m_Name);
printf("Peer Count: %d\n", chat.m_PeerCount);
for(int i=0; i< chat.m_PeerCount; i++)
{
printf("Peer[%d]: %s\n", i, chat.m_PeerList[i]);
}
printf("1");
ret = chat_communicate(&chat);
//Even more Stuff that isn't even called
}
My program outputs the following
File Descriptor: 3
Binding Port: 1234
Name Length: 4
Name: User
Peer Count: 1
Peer[0]: 192.168.2.2
1
Segmentation Fault
It compiles without errors or even warnings.
You can also assume that every string is null-Terminated The stuff i replaced with comments itn't that complicated but just too much to show.
Every value inside the struct is printed with printf right before but when passing this very struct per reference the application crashes.
What i want to know is why i'm getting this Segmentation Fault. Since it appeared while calling a function i thought it is some kind of layout problem but i havn't find anything like that.
Addition:
Because some people weren't able to believe me that the code i hid behind "some stuff" comments doesn't change anything i want to state this here once again. This code just contains a tcp socket communication and only performs read-operations. I also am able to reproduce the error mentioned above without this code so please don't get stuck with it. Parts does not influence the object under observation at all.
Among other potential problems,
this->m_PeerList = malloc(sizeof(char)*peerCount);
is clearly wrong.
m_PeerList is a char **, yet you're only allocating peerCount bytes, which only works if a char * pointer is one byte on your system - not likely.
Replace it with something like
this->m_PeerList = malloc(peerCount * sizeof( *( this->m_peerList ) ) );
Note that sizeof( char ) is always one - by definition.
You're not allocating enough memory for the this->m_Name. It should be on more than this if you want it to store the null-terminated string of the name.
That, or we need more information about the peerList.
Now that you have posted an almost complete code, I was able to spot two problems next to each other:
int chat_init(Chat_t* this, unsigned int nameLen, char* name, unsigned short int bindPort, unsigned int peerCount, char** peerList)
{
this->m_NameLength = nameLen;
this->m_Name = malloc(sizeof(char) * (nameLen + 1)); // correct
//< this->m_Name = malloc(sizeof(char) * nameLen); // wrong
strcpy(this->m_Name, name); // correct
//< memcpy(this->m_Name, name, nameLen); // wrong
...
The lines starting with //< is your original code:
Here you don't allocate enough space, you need to account for the NUL terminator:
this->m_Name = malloc(sizeof(char) * nameLen);
And here you don't copy the NUL terminator:
memcpy(this->m_Name, name, nameLen);
You really need to be aware how strings work in C.
Why don't you debug it yourself. If using GCC, compile your code with options -g -O0. Then run it with gdb:
gdb ./a.out
...
(gdb) r
If it crashes do:
(gdb) bt
This will give exactly where it crashes.
Update: There may be potential problems with your code as found by other users. However, memory allocation related issues will not crash your application just on calling function chat_communicate. There could be different reasons for this behaviour ranging from stack overflow to improper compilation. Without seeing the whole code it is very difficult to tell. Best advice is to consider review comments by other users and debug it yourself.
Related
A segmentation fault occurs when I want to access or modify the value of a struct member in C programming language.
I actually write a battleship networked game in C language (it is a student project). I have a structure named Player:
enum state{PLAYING = 0, WINNER = 1, LOOSER = 2};
enum action{ATTACK = 1, WAIT = 0, NOTHING = -1};
typedef struct Player Player;
struct Player
{
enum action action;
enum state state;
char name[25];
int isFirstPlayer;
Client* client;
Server* server;
Boards* boards;
};
the main function.
int main(int argc, char *argv[])
{
if(argc < 2)
{
errorUsage();
}
// Initialise player
Player player = newPlayer();
// I removed the network initialization here.
// play game
play_game(&player);
}
the segmentation fault occurs in the function play_game(Player* p):
void attack(Player* p)
{
char msg[2];
bzero(msg, strlen(msg));
printf("Where do you want to fire?");
scanf("%s", msg);
while(verifyEntryAttack(msg) != 1)
{
printf("ERROR Entry:\nFormat = A4, C9, ...\nColumns = A B C D E F G H I J\nRows = 0 1 2 3 4 5 6 7 8 9\n");
printf("please try again: ");
scanf("%s", msg);
}
sendData(p, msg);
Box my_attack_box;
my_attack_box.abs = msg[0];
my_attack_box.ord = msg[1]-'0';
updateMarkBoard(p, my_attack_box);
}
void receiveAttack(Player* p)
{
char received_attack[2];
receiveData(p, received_attack);
printf("I have received the attack: %s\n", received_attack);
Box my_attack_box;
my_attack_box.abs = received_attack[0];
my_attack_box.ord = received_attack[1]-'0';
endureAttack(my_attack_box, p);
}
void play_game(Player* p)
{
while(p->state == PLAYING){
printPlayer(p); //print the game boards.
if(p->action == ATTACK){
printf("Your turn to attack.\n");
attack(p); //attack the ennemy
printf("end of attack turn.\n");
} else if(p->action == WAIT){
printf("wait for an attack...\n");
receiveAttack(p); //receive the attack from the ennemy.
printf("end of waiting turn.\n");
}
if(p->action == WAIT){
p->action = ATTACK;
}
else{
p->action = WAIT;
}
}
}
After one turn in the while loop, the program says "segmentation fault". My tests show that is the p->action which is the problem.
See below the program output that shows the problem: outputs screenshot.
The entire code is available here: GitLab repo link.
It's like my program can't access the action member of my player.
Does anyone have any ideas?
char msg[2];
bzero(msg, strlen(msg));
Okay, so here you try to calculate the length of an uninitialized string, a typical source of page faults (and kernel vulnerabilities). strlen does not know your array's size, it simply looks for a zero character and is likely to get out of your page very soon. Even if the program does not crash at this point, bzero will do the trick as it is likely to write memory out of your reach.
Note that a cell is usually described with at least two characters ("C4" or so), so scanf will write the terminating zero character past the end of msg (again, this could be even out of your available memory). Increase msg's size so that it can accommodate at least valid inputs (at least three chars, the more the better). And you don't need to call strlen here; if you want to pre-clear your array, the simplest way would be to initialize it properly: char msg[256] = {'\0'};.
Next, you haven't shown your NewPlayer()'s code, but your struct contains three pointer fields, please double-check they are allocated, and initialized, properly.
I have a problem with a simple malloc/free functions I use in a more complex program and I can't find how to get rid of this problem.
My project looks like :
main.c
while(1){programm();}
I tried a lot of tests to know where it come from but I just can't find a solution...
here is the code part where it seems to bug :
programm.c
void programm(){
... Creating variables and getting infos from socket ...
char a[512];
char b[512];
sprintf(a,"blablabla",strlen(a));
sprintf(b,"blablabla",strlen(b));
char* MessageOut = NULL;
MessageOut = (char*)malloc(strlen(a)+strlen(b));
if(MessageOut==NULL)
printf("MessageOut Is Null\n");
else
printf("%x\n",(uint)MessageOut);
printf("Size of Malloc:%d\n",strlen(a)+strlen(b));
sprintf( (char*)MessageOut, "%s%s",a, b );
MessageOut[0] = 0x02;
MessageOut[1] = Data[1];
MessageOut[2] = Data[2];
MessageOut[3] = 0x03;
byte_nb = sendto(client_socket, (void *)MessageOut, strlen(a)+strlen(b), 0, (struct sockaddr *)&dist_addr, addr_len);
if (byte_nb == -1) {
printf("send error:%s\n", strerror(errno));
} else {
printf("%i bytes sent\n", byte_nb);
}
printf("%s\n",MessageOut);
if(MessageOut==NULL)
printf("MessageOut Is Null\n");
else
printf("%x\n",(uint)MessageOut);
free(MessageOut);
printf("Test\n");
}
As I said it is just a part of my code, I tried to summarize it to the part where it goes wrong.
All of this is in a while(1)-loop.
The error I got is double free or corruption (!prev)
The printf give me :
1c7eeb0
Size Of Malloc : 196
196 Bytes sent
1c7eeb0
The first loop works correctly but after a few one I got
Error: double free or corruption (!prev): 0x01c7eeb0
It does not seems to be a problem with the socket because I have the same address before and after the sendto.
Here
sprintf(a,"blablabla",strlen(a));
strlen() is passed an uninitialised a which invokes undefined behaviour.
To initially set a initialise it on definition:
char a[512] = "blablabla";
or set it right after:
char a[512];
strcpy(a, "blablabla");
(The same applies to b)
Assuming a and b were set correctly this call
sprintf( (char*)MessageOut, "%s%s",a, b );
would write 1 char beyond MessageOut bounds, as after setting the data as per a and b and additional '\0' will be put, the so called 0-terminator, that every C-"string" carries to maker is end.
To fix this adjust the related call to malloc() accordingly:
MessageOut = malloc(strlen(a) + strlen(b) + 1); /* There is no need to cast
the result fo malloc in C. */
void main(int argc, char* argv[]) {
char* hostname = (char*)malloc(sizeof(char)*1024);
hostname = getClientHostName("122.205.26.34");
printf("%s\n", hostname);
free(hostname);
}
char* getClientHostName(char* client_ip) {
char hostnames[5][2];
hostnames[0][0] = "122.205.26.34";
hostnames[0][1] = "aaaaa";
hostnames[1][0] = "120.205.36.30";
hostnames[1][1] = "bbbbb";
hostnames[2][0] = "120.205.16.36";
hostnames[2][1] = "ccccc";
hostnames[3][0] = "149.205.36.46";
hostnames[3][1] = "dddddd";
hostnames[4][0] = "169.205.36.33";
hostnames[4][1] = "eeeeee";
for(int i = 0; i<5; i++) {
if(!strcmp(hostnames[i][0], client_ip))
return (char*)hostnames[i][1];
}
return NULL;
}
Beginner in C.
I am not sure if there would be a better way to implement what I am trying to implement. The code is self-explanatory. Is there any way that I can predefine the size of hostname, using some general size of IP addresses, to avoid seg fault? Is there a even better way where I don't have to hardcode the size?
After fixing the compiler errors and warnings you get:
const char* getClientHostName(const char* client_ip) {
const char * hostnames[5][2];
hostnames[0][0] = "122.205.26.34";
hostnames[0][1] = "aaaaa";
hostnames[1][0] = "120.205.36.30";
hostnames[1][1] = "bbbbb";
hostnames[2][0] = "120.205.16.36";
hostnames[2][1] = "ccccc";
hostnames[3][0] = "149.205.36.46";
hostnames[3][1] = "dddddd";
hostnames[4][0] = "169.205.36.33";
hostnames[4][1] = "eeeeee";
for(int i = 0; i<5; i++) {
if(!strcmp(hostnames[i][0], client_ip))
return hostnames[i][1];
}
return NULL;
}
int main(int argc, char* argv[]) {
const char * hostname = getClientHostName("128.205.36.34");
printf("%s\n", hostname);
}
Is there a even better way where I don't have to hardcode the size?
Take the habit to compile with all warnings and debug info: gcc -Wall -Wextra -g with GCC. Improve the code to get no warnings at all.
If you want to get genuine IP addresses, this is operating system specific (since standard C11 don't know about IP addresses; check by reading n1570). On Linux you would use name service routines such as getaddrinfo(3) & getnameinfo(3) or the obsolete gethostbyname(3).
If this is just an exercise without actual relationship to TCP/IP sockets (see tcp(7), ip(7), socket(7)) you could store the table in some global array:
struct myipentry_st {
const char* myip_hostname;
const char* myip_address;
};
then define a global array containing them, with the convention of terminating it by some {NULL, NULL} entry:
const struct myipentry_st mytable[] = {
{"aaaaa", "122.205.26.34"},
{"bbbb", "120.205.36.30"},
/// etc
{NULL, NULL} // end marker
};
You'll better have a global or static variable (not an automatic one sitting on the call stack) because you don't want to fill it on every call to your getClientHostName.
Then your lookup routine (inefficient, since in linear time) would be:
const char* getClientHostName(char* client_ip) {
for (const struct myipentry_st* ent = mytable;
ent->myip_hostname != NULL;
ent++)
// the if below is the only statement of the body of `for` loop
if (!strcmp(ent->myip_address, client_ip))
return ent->myip_hostname;
// this happens after the `for` when nothing was found
return NULL;
}
You could even declare that table as a heap allocated pointer:
const struct myipentry_st**mytable;
then use calloc to allocate it and read its data from some text file.
Read the documentation of every standard or external function that you are using. Don't forget to check against failure (e.g. of calloc, like here). Avoid memory leaks by appropriate calls to free. Use the debugger gdb and valgrind. Beware of undefined behavior.
In the real world, you would have perhaps thousands of entries and you would perform the lookup many times (perhaps millions of times, e.g. once per every HTTP request in a web server or client). Then choose a better data structure (hash table or red-black tree perhaps). Read some Introduction to Algorithms.
Add * to type definition char * hostnames[5][2]. This must be array of pointers, not simple chars. Another necessary change is strcpy instead of = in strcpy( hostname, getClientHostName("122.205.26.34") );.
PS: Always try to compile with 0 compiler warnings, not only 0 errors!
I'm programming atmega8535 using C. I want to save data into flash disk using ALFAT OEM module. But, I have problem because the data that I want to save change into other variable in the middle program (Data saving is success, but the data is wrong). It occurs after malloc. I already malloc the variable data. I'm using hyperterminal to debugging my program
This is my code. I only show that related
// Declare your global variables here
char* reply = NULL;
char* directory = NULL;
char* fileName = NULL;
char* getFileName = NULL;
void writeCommand(char* command){ //to give command to ALFAT
//not related
}
void readCommand(){ //to request reply from ALFAT
//related (because contains malloc and also change my variable) but I give another example
}
void get_ErrorCode(char errorCode[4]){ //to get errorCode from ALFAT's reply
//not related
}
void get_Version(){ //to know ALFAT's version
//not related
}
void mountUSB0(){ //to mount USB port 0
//not related
}
void mountUSB1(){ //to mount USB port 1
//not related
}
void get_fileName(){ //to get fileName from ALFAT's reply after N command
//not related
}
int check_File(char port[1]){ //to check whether file already exists or not
//related (because contains malloc and also change my variable) but I give another example
}
void separate_Directory(char* fullDir, char* data){ //to separate directory and fileName from fullDirectory "fullDir"
int i,j;
int numSlash = 0; //numberOfSlash
int curNumSlash = 0; //currentNumberOfSlash
//CHECK THE DATA BEFORE MALLOC
printf("1st GUNYUH data = %s, address data = %x, directory = %s, address directory = %x\n",data,data,directory,directory);
//count backslash '\'=0x5C
for (i=0;i<strlen(fullDir);i++){
if(fullDir[i]== 0x5C ) numSlash++;
}
//count number of char for directory
i=0;
curNumSlash = 0;
while (curNumSlash != numSlash){
if(fullDir[i]== 0x5C) curNumSlash++;
i++;
}
//i = number of char for directory
//number of char for filename = strlen(fullDir)-total char directory
do{
directory = (char *) malloc (i+1);
}while(directory==NULL);
do{
fileName = (char *) malloc (strlen(fullDir)-i+1);
}while(fileName==NULL);
//CHECK THE DATA AFTER MALLOC (ALREADY CHANGED)
printf("2nd GUNYUH data = %s, address data = %x, directory = %s, address directory = %x\n",data,data,directory,directory);
//save into directory until last backslash
i=0;
curNumSlash = 0;
while (curNumSlash != numSlash){
if(fullDir[i]== 0x5C) curNumSlash++;
directory[i] = fullDir[i];
i++;
}
directory[i] = '\0';
//remaining fullDir into fileName
j=0;
while (i < strlen(fullDir)){
fileName[j] = fullDir[i];
i++;
j++;
}
fileName[j] = '\0';
//CHECK THE DATA AGAIN (CHANGED INTO directory)
printf("3rd GUNYUH data = %s, address data = %x, directory = %s, address directory = %x\n",data,data,directory,directory);
printf("separate directory = %s, fileName = %s, fullDir = %s\n",directory,fileName,fullDir);
}
void writeData (char* data, char* fullDir, char port[1], char statFileHandler[16]){
//I omit that not related
printf("1)!!!!!!!!!!!!!!!!DATA = %s, ADDRESS DATA = %x, DIRECTORY = %s, ADDRESS DIRECTORY = %x\n",data,*data,directory,*directory);
separate_Directory(fullDir,data);
printf("2)!!!!!!!!!!!!!!!!DATA = %s, ADDRESS DATA = %x, DIRECTORY = %s, ADDRESS DIRECTORY = %x\n",data,*data,directory,*directory);
//omitted
}
void main(){
char* data;
char* fullDir = NULL;
char port[1]="";
char statFileHandler[16];
//omitted
while(1){
//omitted (also omit the mounting)
do{
data = (char *) malloc (strlen("meong")+1); //+1 utk \0
}while(data==NULL);
strcpy(data,"meong");
data[strlen("meong")] = '\0';
fullDir = (char *) malloc (strlen("\\f1\\nyan.txt")+1);
strcpy(fullDir,"\\f1\\nyan.txt");
fullDir[strlen("\\f1\\nyan.txt")] = '\0';
for(i=0;i<strlen("\\f1\\nyan.txt");i++){
fullDir[i] = toupper(fullDir[i]);
}
//omit some printf for debugging
printf("fullDir di main= %s\n",fullDir);
printf("data di main = %s\n",data);
printf("address data di main = %x\n",*data);
writeData (data, fullDir, port, statFileHandler);
break;
}
while(1){}
}
}
}
Check the GUNYUH part. The output in HyperTerminal:
1st GUNYUH data = meong, address data = 196, directory = , address directory = 0
2nd GUNYUH data = , addressdata = 196, directory = , address directory = 196
3rd GUNYUH data = \F1\, address data = 196, directory = \F1\, address directory = 196
my data in main is "meong".
1st GUNYUH before malloc, the data still "meong"
2nd GUNYUH after malloc, the data already changed
3rd GUNYUH after defined the directory, the data also changed. (Well because the address also same so it point to the same address)
why it changed?
Is it because lack of memory problem? But, when there's no enough heap memory, the malloc will return NULL so it never go out from the loop. I already experienced the lack of heap memory before and it did can't go out from the loop.
I have also experience overlapping like this. But it is because I didn't use malloc. (but I didn't check the address and go for static array but not enough memory so back into dynamic and found that it need malloc)
some help please?
This is not an answer but it is too big for comments.
You have the following bugs:
In four different printf lines you cause undefined behaviour by passing null pointer for %s. (the variable directory). After undefined behaviour has begun, all bets are off.
Printing a pointer with %x causes undefined behaviour. To print a pointer use %p and cast the pointer to (void *) .
You do *THING instead of THING in 3 different places, for printf
Don't cast malloc, the cast may be hiding an error message indicating a bug
On the line for(i=0;i<strlen("\\f1\\nyan.txt");i++){ , i is undeclared.
You failed to include stdio.h, stdlib.h string.h and ctype.h .
There are two more } than { in your code.
After the line with fullDir = (char *) malloc... , you do not check to see whether malloc failed.
This code should not compile. This leads me to believe that you are not posting your real code. It is important that you post exactly the code that is failing.
You need to create a minimal program, test that that program still shows the problem, and post the code of that program unaltered.
This is because there could be problems that are in the "real code" but not in the code you posted. Since you don't know where the problem is, you can't be sure that you have included the part that causes the problem.
In fact, if I fix all the bugs listed above and remove the infinite loop at the end of main(), your code compiles and runs successfully for me. That suggests that either one of the listed points is the problem, or the problem is in code that you didn't post.
Is there any reason that a program, which compiled earlier, should seg fault at a point because of fgets? I changed no code related to it AT ALL. Suddenly I believe it is failing to open the file, but I tested it with the file like fifteen minutes ago.... All I did was add a search function, so I don't understand what the issue is.....
Could it be the server I'm connecting to over PuTTy?
int createarray( int **arrayRef, FILE *fptr){
int size = 0, i;
char rawdata[100];
while (fgets(rawdata, 99, fptr) != NULL){
size++;
}
rewind(fptr);
*arrayRef = malloc(sizeof(int) * size);
for ( i = 0; i < size; i++ ){
fgets(rawdata, 99, fptr);
*(*arrayRef + i) = atoi(rawdata);
}
return size;
}
int main ( int argc, char **argv ) { //main call
// declare variable to hold file
FILE *inFilePtr = fopen(*(argv + 1), "r");
int **aryHold;
int numElements, sortchoice, key, foundindex;
// Call function to create array and return num elements
numElements = createarray(aryHold, inFilePtr);
This is the code that compiled, performed correct, and hasn't been changed since. GDB says there is an error with fgets.
OK, the reason it use to "work" is you were clobbering an unimportant memory location. Changing your code shifted things around and now you are clobbering something important.
You're passing an uninitialized pointer to createarray(). You wanted to do something like:
int* aryHold;
//...
... createarray(&aryHold ...
BTW, many compilers have the ability to catch this kind of error for you. If you haven't already, you might want to see if your compiler has an error checking option that could have saved you hassling with this (and perhaps find some other code that only "works" accidentally).