strcpy resulted in bad access or fault segmentation [duplicate] - c

This question already has answers here:
Correctly allocating multi-dimensional arrays
(2 answers)
Closed 5 years ago.
Here is a shell program I wrote for honing my understanding on C pointer and array. This shell program has the functionalities of reading in commands (execute them in execvp()) and the history feature can store 10 commands (similar to Linux terminal) where "!!" returns latest command and execute, !Nth returns Nth command and execute, otherwise read command and store them in history array. When requested history command doesn't exist, relevant error message printed. For full code reference, see Shell_Program_C.
initialize() method initialize each history character string array with letter 'e' ('e' means empty or string hasn't been assigned) so that I could later check that history string has value or not. readHist() method assign each individual command to the history string array, char** hist which has a size of 10.
My problem is:strcpy(hist[histC], tokens[count])in readHist() is returning 'bad access' here.
Expected behavior: each command should be copied to char** hist as a string of char so that later requested command can be retrieved and executed.
char** initialize() {
char** hist = malloc(10 * sizeof(char *));
for (int i = 0; i < 10; ++i) {
hist[i] = (char *)malloc((MAX_LINE / 2) + 1);
for(int j = 0; j < (MAX_LINE / 2); j++) {
hist[i][j] = 'e';
}
}
return hist;
}
void readHist(char**hist, int histC ,char** tokens, int count) {
histC = (histC - 1) % 10;
for(int i = 0; i < count; i++) {
size_t strlenth = strlen(tokens[i]);
//strcat(hist[histC], tokens[count]);
if(count > 1) {
strcat(hist[histC], tokens[count]);
hist[histC][strlenth] = ' ';
} else {
printf("histC%d", histC);
strcpy(hist[histC], tokens[count]); // bad access or segmentation fault
hist[histC][strlenth] = '\0';
}
}
}

Your SegFault is due to violating the strcat requirement that "The strings may not overlap" This looks like a careless oversight that has big consequences. Specifically, look at cmdargv below:
histCheck(cmdargv, &histCount, cmdargv, count, &isAmp);
You are passing the same array of pointers cmdargv as the parameters that are passed to hist and tokens in your call to:
void histCheck(char**hist, int* histCount, char**tokens, int tcount, int* amp)
In histCheck both hist and tokens point to the same memory that can be seen in a debugger, e.g.
histCheck (hist=0x7fffffffd9b0, histCount=0x7fffffffd9a8, tokens=0x7fffffffd9b0
note the address of both hist and tokens.
This same error is then passed to readHist, e.g.
readHist (hist=0x7fffffffd9b0, histC=1, tokens=0x7fffffffd9b0
which results in your call to strcat attempting to concatenate overlapping strings (the same string), e.g.:
strcat (hist[histC], tokens[count]);
(note: are you sure you want count above?)
which results in your familiar:
Program received signal SIGSEGV, Segmentation fault.
__strcat_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:296
296 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.
Now I'm not saying your problems are limited to that (note my comment about he update to count in checkAmp), so you have more work to do. But your SegFault is no longer a mystery.
It appears you intended:
histCheck (hist, &histCount, cmdargv, count, &isAmp);
You will also want to revisit:
strcat (hist[histC], tokens[count]);
which will lead to your very next SegFault. Here it appears you want:
strcat (hist[histC], tokens[i]);
Also, in your rework of your code, pay careful attention to resetting all values with each iteration around your do loop in main to prevent leaving stray values in cmdargv, etc... You will also need some way to free the memory you allocate to prevent leaking memory on subsequent calls to malloc in your various functions.
You will want to make friends with a debugger. There is no way around it, especially when you are chopping the flow up into a number of small inter-related functions to compartmentalize the code. Nothing wrong with that, it just make the debugger all the more important to figure out where the wheels are coming off -- and why...
Rework your code and post any further problems you have. To bandaid the count problem in checkAmp, you may consider something like:
void checkAmp (int *count, char** tokens, int *Amp) {
size_t strlenth = strlen(tokens[*count - 1]);
if((strlenth == 1) && tokens[*count - 1][0] == '&')
{
*Amp = 1;
tokens[*count - 1] = NULL;
*count = *count -1;
} else {
tokens[*count] = NULL;
}
}
(and updating the call to checkAmp as well)
Lastly, while not an error, the standard coding style for C avoids the use of caMelCase or MixedCase variable names in favor of all lower-case while reserving upper-case names for use with macros and constants. It is a matter of style -- so it is completely up to you...

Related

Why my code doesn't produce correct outputs for some cases when placing it in a function while inlining it to the main method does just fine?

I already asked this question in combination with another question, but I thought those are irrelevant to each other and honestly only one was getting answered, so I created a separate question thread to maximize my chances of solving this and to stop plugging my hair out.
So, The Asked problem is simple : print only unique words from a sentence (in order). Now I already brewed up my code Used strtok() to split up the string and it works just fine but the problem shows its head when I try to
separate the said code to a function, it suddenly fails one test case. Let me show you what I mean :
The Code in question, inlined to the main method itself
int exists(char words[][MAX], int n, char *word){
for(int i=0;i < n;i++)
if(strcmp(words[i],word) == 0)
return 1;
return 0;
}
int main(){
char sentence[MAX*50] = {0}; //arbitary length
fgets(sentence,MAX*50,stdin);
//Solution to the Said Problem
char words[10][MAX] = {0};
int wi=0;
for(char* tok=sentence;(tok=strtok(tok," \n"))!=NULL;tok=NULL)
if(exists(words,wi,tok)==0)
strcpy(words[wi++],tok);
for(int i=0;i<wi;i++) printf("%s ",words[i]);
}
Results, Inlined
The Code in question, separated as a Function
int exists(char words[][MAX], int n, char *word){
for(int i=0;i < n;i++)
if(strcmp(words[i],word) == 0)
return 1;
return 0;
}
void purgeDuplicates(char* sentence){//The code with not even a change to its whitespaces
char words[10][MAX] = {0};
int wi=0;
for(char* tok=sentence;(tok=strtok(tok," \n"))!=NULL;tok=NULL)
if(exists(words,wi,tok)==0)
strcpy(words[wi++],tok);
for(int i=0;i<wi;i++) printf("%s ",words[i]);
}
int main(){
char sentence[MAX*50] = {0}; //arbitary length
fgets(sentence,MAX*50,stdin);
purgeDuplicates(sentence);
}
Results, In Function
The Output Of the Program(for both) is :
Input :
ab cd gh ef ab ab gh cd
Output :
ab cd gh ef
Now what I tried :
Changed function parameter datatype signature for sentence to char**, and passed the address of the first index of the sentence [By copying it to a pointer first](Might have screwed it up).
Copied the whole array to a new character array and passed it to function [Same Results].
Copied the whole array to a new character array inside function [same story].
Changed to accept parameter as Array instead of pointer[Same Story].
Debugged the program but couldn't get any viable information regarding the problem, but what I gathered is strtok() modifies the original string by placing '\0' on areas where delimiters are present in string. But it is doing it on both scenarios and linked list implementation of the solution uses strtok in its function (and it is changing the original string as previously said) yet it produces correct results.
Note : All methods are executed in separate instances and not back to back

Is there a better way of modifying arrays from within a function in C?

I am trying to create a formatted string , however I do not know why I cannot print global array which I have modified inside the function.Also the strange behavior is that I cannot access only a specific global array (rand_session_key) rest of the other global arrays are behaving as normal(similar operations are being done on them except their size varies) and I can access their value properly. This code is run on an esp32 (DOIT Dev Kit V1) (with Arduino-Core) , when I run this program on my computer (modifying a few functions etc.) the result is what I expect , I think I am overlapping the characters in the memory or accessing it the wrong way , but had it been the case I would not have yielded the expected output on my computer.
I tried to modify my program and made it more verbose. Also I ran the same code (with some obvious modifications to make it run on my computer) , and the result is good as expected.
char persistent_peripheral_id[] = "FRUCTOSE96";
char rand_session_iden[7] = {'\0'};
char rand_session_key[17] = {'\0'};
char rand_session_channel[3] = {'\0'};
char *generate_random_session_identifier(char *rand_session_iden_local)
{
srand(time(NULL));
int counter = 0;
for (counter = 0; counter < 6; counter++)
*(rand_session_iden_local + counter) = (random(10) % ('~' - ' ')) + 'k';
rand_session_iden_local[counter] = '\0';
printf("Identifier : %s\n", rand_session_iden); //acessing global defintion of array everything is good until here
return &rand_session_iden_local[0];
}
char *generate_random_session_key(char *rand_session_key_local)
{
srand(time(NULL));
int counter = 0;
for (counter = 0; counter < 16; counter++)
*(rand_session_key_local + counter) = (random(10) % ('~' - ' ')) + 'b';
rand_session_key_local[counter] = '\0';
printf("Key : %s\n", rand_session_key);//acessing global defintion of array everything is good until here
return &rand_session_key_local[0];
}
char *generate_random_session_channel(char *rand_session_channel_local)
{
srand(time(NULL));
int channel_value = random(100);
sprintf(rand_session_channel_local, "%03ld", channel_value);
printf("Channel : %s\n", rand_session_channel);//acessing global defintion of array everything is good until here
return &rand_session_channel_local[0];
}
void begin_exchange_package()
{
//If this does not works here (observe rand_session_key) , it will not work for sprintf also ??
printf("\n %s-%s-%s-%s \n", (char *)persistent_peripheral_id,
generate_random_session_identifier(rand_session_iden),
generate_random_session_key(rand_session_key),
generate_random_session_channel(rand_session_channel));
//Notice it prints here ????
printf("\n %s \n",generate_random_session_key(rand_session_key));
Serial.println("Done");
//sprintf((char *)plain_text_package, "{\"p\":\"%s\",\"r\":\"%s\",\"k\":\"%s\",\"c\":\"%s\"}", (char *)persistent_peripheral_id,(char *)rand_session_iden, (char *)rand_session_key , (char *)rand_session_channel);
}
void setup()
{
Serial.begin(115200);
begin_exchange_package();
}
void loop()
{
}
The Output is
FRUCTOSE96-tnltkp--094
Where I expected all the 4 arrays to be printed ?? but it does print separately , is my array being terminated in the wrong way ?? also the logic to assign a random character will always yield a printable ASCII Character (I learned this from a forum on esp32's website)
This code ...
sprintf(rand_session_channel_local, "%03ld", channel_value);
... requires rand_session_channel_local to point to an array of at least four characters, because at will print at least three digits plus a string terminator. The array into which it points, rand_session_channel, is only three characters long. The resulting behavior is undefined.
The observed manifestation of the UB is consistent with the global arrays being laid out in memory such that rand_session_key immediately follows rand_session_channel, such that overflowing the latter means that the string terminator is written to position 0 of the former, making it an empty string. Note, however, that you cannot rely on predicting manifestations of UB, nor is it generally of much use to analyze them. Instead, avoid exercising UB.
It's unclear what random function you are using, since the C standard library's does not take an argument, but if the argument to yours specifies an exclusive upper bound then you could just change the sprintf format to "%02ld". Alternatively, increase the size of rand_session_channel to at least 4.

Segmentation fault on copying string elements to another string

Why am I getting segmentation fault? I have listed my code below.
Please tell if anyone knows what is my fault here and how do I correct it?
What I am trying to do here
I am trying to take numbers as input and for them I have to output a string of characters.
Problem
link to the problem is here.
The code of my proposed solution
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
long long int n, k;
char manku[] = { 'm', 'a', 'n', 'k', 'u' };
char l[10000000];
int t, i = 0, j, p;
scanf("%d", &t);
while (t > 0)
{
scanf("%lld", &n);
while (n > 0)
{
j = n % 5;
if (j == 0)
l[i] = manku[4];
else
l[i] = manku[j - 1];
n = n / 5;
i++;
}
p = strlen(l);
for (i = 0; i < p; i++)
l[i] = l[p - 1 - i];
for (i = 0; i < p; i++)
printf("%c", l[i]);
t--;
}
return 0;
}
char l[10000000];
This huge array is overflowing your stack memory.
The stack memory segment is an area of memory allotted for automatic variables and its size is fairly small. It is not a good idea to have such a huge array in stack.
Try to allocate it dynamically, like this:
char *l;
l = malloc(10000000); //note: size of char is 1
With this, the memory allocated to l in heap segment. Make sure to free it once you done with it.
Alternatively, you can make l a global variable or a static local variable so that it will go in Data Segment.
You are getting a segmentation fault when you start running your binary because you are running out of stack memory due to the big size of your array char l[10000000] (you can check the size of your stack by running
$ ulimit -s
in your shell).
There are at least two solutions to this:
Increase the size of your stack. You can do this by running, e.g.,
$ ulimit -s unlimited
in your shell before running the binary.
Use malloc to allocate the l array, so that it is allocated in the heap rather than in the stack.
Firstly, initialize the variable i after scanning n.
while(t>0) {
scanf("%lld",&n);
i = 0; /* initialize i every time here */
while(n>0) {
/* some code */
}
}
Also instead of creating stack created array like char l[10000000]; create the dynamic array once before while loop and free the dynamically allocated memory once done. for e.g
char *l = malloc(SIZE); /* define the SIZE */
...
...
free(l);
Short Answer: The segmentation fault is caused by char l[10000000];. Decalring char l[26]; is sufficient.
Details
As others said the allocation char l[10000000]; causes the segmentation fault. You do not need this much memory. The question stated that the maximum value for n is 10^18. Thus the maximum length of a word would be 26 characters. Thus, char l[26]; is sufficient.
Explanation: It is given that you have 10^18 options to arrange k characters. Each charater has 5 options and thus the number of options to arrange these characters is 5^k. Now, you just have to find k:
5^k = 10^18 ==> k = log_5(10^18) ~= 25.75218 < 26
Implementation
Regarding the implementation, you have few wrong things going on.
You do not set i = 0; after each input scan.
Your can not use strlen without the terminating null-character. You should add l[i] = '\0'; above p = strlen(l);.
Your second for loop, the one that should revert the string, is not working properly. Each step changes the string and the steps after it use the changed string (instead of working with the original one).
Regarding the algorithm, it does not work properly as well. I can give you a hint: this problem is similar to counting in base-5.
Comments
The things above are just few things that I have noticed. I think you should consider rewriting the code since it may still contaion small flaws.
Another tip: for printing strings (character arrays in c) you can use
printf("%s", str);
Assuming that str is an array of character that ends with the terminating null-character. Some more information here.

Segmentation fault when indexing into char array via pointer

My code is causing a segmentation fault when accessing an array element even though that element was already accessed without a problem.
int charToInt(char a)
{
int b;
if(isdigit(a))
{
b = a - '0' - 1;
}
if(isalpha(a))
{
b = a - 65;
}
return b;
}
int validPosition(char **array, int r, int c, char* position, int slots)
{
int i,k;
if(strlen(position) == 5)
{
if(!isalpha(position[0]) || !isdigit(position[1]) || position[2]!=' ' || (position[3]!='N' && position[3]!='E' && position[3]!='W' && position[3]!='S')) //lathos gramma
{
printf("\n%s", "Invalid answear.This is an example of a valid answear: A5 N");
return 2;
}
if( charToInt(position[0]) > r - 1 || charToInt(position[1]) > c - 1 )//ama vgainei eksw apo ta oria
{
printf("\n%s", "The position you choosed is out of the bountries...");
return 2;
}
printf("\n%s%c%s","position[3] is: ",position[3], " but it doesn't work >_<"); // position[3] is N
if(position[3] == 'N') //the problem is here <~~~~~~~~~~~~~~~~~~~<
{
printf("\n%s", "come on");
if(charToInt(position[0]) + slots < r)
{
for(i=charToInt(position[0])-1; i<charToInt(position[0])+slots; i++)
{
if(array[i-1][charToInt(position[1])-1] != '.')
{
printf("\n%s", "The position you choosed is not valid because there is oneother ship there");
return 2;
}
}
}
else
{
printf("\n%s", "The ship is going out of the bountries...");
return 2;
}
}
}
}
When position holds the string "A9 N", the printf correctly outputs 'N' for position[3]. For some reason when it tries to do if(position[3] == 'N'), however, a segmentation fault occurs.
Example program run:
Example of positioning: G3 E
Aircraft carrier (5 places), Give location and direction: A9 N
1
position[3] is: N but it doesn't work >_<
Well, based on your updates, it seems you have a variety of problems. For future reference, actually adding in the (possibly simplified) code showing how you were calling the function in question is better than trying to describe it using prose in a comment. There will be less guesswork for the people trying to help you.
If I'm reading your comment correctly, the code that calls validPosition looks something like this:
// "r and c are 9 and 9 in the specific example(rows columns)."
int rows = 9;
int columns = 9;
// "slots=5."
int slots = 5;
// "array is a 2d array and it contains characters(created with malloc)."
char **array = malloc(rows * columns * sizeof(char));
// "i created char position[10] in the function that called this function"
char position[10];
// "and with fgets(position, 10, stdin); i putted A9 N inside it."
fgets(position, 10, stdin);
validPosition(array, rows, columns, position, slots);
The first problem is your description of the allocation of array (I apologize if I misunderstood your comment and this isn't actually what you are doing). It should look similar to the code below for a dynamically sized two-dimensional array used with two subscripting operations (array[index1][index2], as it is in validPosition). Pointers-to-pointers (char **array) act differently than fixed sized multi-dimensional arrays (array[SIZE1][SIZE2]) when you access them that way.
// each entry in array should be a pointer to an array of char
char **array = malloc(rows * sizeof(char*));
for(i = 0; i < rows; i++)
array[i] = malloc(columns * sizeof(char));
You also need to be careful about using position after the fgets call. You should check the return value to make sure it isn't NULL (indicating an EOF or error condition). The string may not be \0-terminated in this case. In fact, all the elements may still be uninitialized (assuming you didn't initialized them before the call). This can lead to undefined behavior.
The next issue is that validPosition does not return a value on every code path. One example is if strlen(position) != 5. The other is if you enter the for loop and array[i-1][charToInt(position[1])-1] != '.' is never true (that is, the ship placement is deemed valid).
As strange as it is for an English speaker to say this to a Greek author, lets ignore internationalization and focus only on the default C local. The checks on position[0] should therefore be sufficient, though you might consider allowing your users to use lowercase letters as well. When converting position[1] from 1-based to 0-based, however, you do not account for the case when it is '0', which will result in charToInt returning -1. Furthermore, you're erroneously doing the subtraction again in the second array subscript of array[i-1][charToInt(position[1])-1].
Similarly, as pointed out by Jite and BLUEPIXY, you are doing two extra subtractions on the result of charToInt(position[0]): one in the for loop initializer (i=charToInt(position[0])-1) and one in the first array subscript of array[i-1][charToInt(position[1])-1].
Once you fix that, you might find that you are sometimes incorrectly telling the user that their selection is invalid. This is because you are checking charToInt(position[0]) + slots < r instead of <= r.
As I mentioned in my comment, one of the accesses to array is very probably the culprit behind your segmentation violation, not position[3] == 'N'. The reason you don't see the output of printf("\n%s", "come on"); is that your stdout appears to be line-buffered and there's no end of line to flush it. It is generally automatically flushed on normal program termination, however you're seg-faulting so that doesn't happen.
Finally, these are only the semantic errors I noticed. Stylistically, the code could also stand to be improved. For instance, it seems you're going to be implementing else if(position[3] == 'E', else if(position[3] == 'W', and else if(position[3] == 'S' clauses with similar logic to your if(position[3] == 'N' clause. This increases the likelihood you'll introduce an error by incorrectly copying-and-pasting and also increases your work later when you need to make a change in four places instead of one.
Since the terminology 'Segmentation Fault' I believe you are on Linux machine.
Use gdb to find the cause of error. Here are the steps.
Compile with additional -g flag (ex. gcc -g my_prog.c)
Run debugger: gdb a.out
Use 'list' command to find the line for break point (eg. first line of your function)
Set breakpoint on that line with: b 25 (if 25 is that line)
Run program with 'run' command
Use command 'next' to execute next line of code
Now the execution will pause on that line, you can examine memory, print variable contents
and stuff. But generally you want to determine on which line the execution fails and what was in which variable.
With a little playing with memory, you will easily find where the problem is. Personally, my code wont work with gdb support.
Perhaps segmentation fault at array[i-1][charToInt(position[1])-1]
i:charToInt(position[0])-1 : charToInt('A') - 1 : -1 <- Array out-of-bounds

Trying to free memory after calling strcpy causes the program to crash

I understand that a lot of people here complain about strcpy, but I haven't found anything using search that addresses the issue I have.
First off, calling strcpy itself doesn't cause any sort of crash/segmentation fault itself. Secondly, the code is contained within a function, and the first time that I call this function it works perfectly. It only crashes on the second time through.
I'm programming with the LPC1788 microcontroller; memory is pretty limited, so I can see why things like malloc may fail, but not free.
The function trimMessage() contains the code, and the purpose of the function is to remove a portion of a large string array if it becomes too large.
void trimMessage()
{
int trimIndex;
// currMessage is a globally declared char array that has already been malloc'd
// and written to.
size_t msgSize = strlen(currMessage);
// Iterate through the array and find the first newline character. Everything
// from the start of the array to this character represents the oldest 'message'
// in the array, to be got rid of.
for(int i=0; i < msgSize; i++)
{
if(currMessage[i] == '\n')
{
trimIndex = i;
break;
}
}
// e.g.: "\fProgram started\r\nHow are you?\r".
char *trimMessage = (char*)malloc((msgSize - trimIndex - 1) * sizeof(char));
trimMessage[0] = '\f';
// trimTimes = the number of times this function has been called and fully executed.
// freeing memory just below is non-sensical, but it works without crashing.
//if(trimTimes == 1) { printf("This was called!\n"); free(trimMessage); }
strcpy(&trimMessage[1], &currMessage[trimIndex+1]);
// The following line will cause the program to crash.
if(trimTimes == 1) free(trimMessage);
printf("trimMessage: >%s<\n", trimMessage);
// Frees up the memory allocated to currMessage from last iteration
// before assigning new memory.
free(currMessage);
currMessage = malloc((msgSize - trimIndex + 1) * sizeof(char));
for(int i=0; i < msgSize - trimIndex; i++)
{
currMessage[i] = trimMessage[i];
}
currMessage[msgSize - trimIndex] = '\0';
free(trimMessage);
trimMessage = NULL;
messageCount--;
trimTimes++;
}
Thank you to everyone that helped. The function works properly now. To those asking why I was trying to print out an array I just freed, that was just there to show that the problem occurred after strcpy and rule out any other code that came after it.
The final code is here, in case it proves useful to anyone who comes across a similar problem:
void trimMessage()
{
int trimIndex;
size_t msgSize = strlen(currMessage);
char *newline = strchr(currMessage, '\n');
if (!newline) return;
trimIndex = newline - currMessage;
// e.g.: "\fProgram started\r\nHow are you?\r".
char *trimMessage = malloc(msgSize - trimIndex + 1);
trimMessage[0] = '\f';
strcpy(&trimMessage[1], &currMessage[trimIndex+1]);
trimMessage[msgSize - trimIndex] = '\0';
// Frees up the memory allocated to currMessage from last iteration
// before assigning new memory.
free(currMessage);
currMessage = malloc(msgSize - trimIndex + 1);
for(int i=0; i < msgSize - trimIndex; i++)
{
currMessage[i] = trimMessage[i];
}
currMessage[msgSize - trimIndex] = '\0';
free(trimMessage);
messageCount--;
}
free can and will crash if the heap is corrupt or if you pass it an invalid pointer.
Looking at that, I think your first malloc is a couple of bytes short. You need to reserve a byte for the null terminator and also you're copying into offset 1, so you need to reserve another byte for that. So what is going to happen is that your copy will overwrite information at the start of the next block of heap (often used for length of next block of heap and an indication as to whether or not it is used, but this depends on your RTL).
When you next do a free, it may well try to coalesce any free blocks. Unfortunately, you've corrupted the next blocks header, at which point it will go a bit insane.
Compare these two lines of your code (I've respaced the second line, of course):
char *trimMessage = (char*)malloc((msgSize - trimIndex - 1) * sizeof(char));
currMessage = malloc((msgSize - trimIndex + 1) * sizeof(char));
Quite apart from the unnecessary difference in casting (consistency is important; which of the two styles you use doesn't matter too much, but don't use both in the same code), you have a difference of 2 bytes in the length. The second is more likely to be correct than the first.
You allocated 2 bytes too few in the first case, and the copy overwrote some control information that malloc() et al depend on, so the free() crashed because you had corrupted the memory it manages.
In this case, the problem was not so much strcpy() as miscalculation.
One of the problems with corrupting memory is that the victim code (the code that finds the trouble) is often quite far removed from the code that caused the trouble.
This loop:
for(int i=0; i < msgSize; i++)
{
if(currMessage[i] == '\n')
{
trimIndex = i;
break;
}
}
could be replaced with:
char *newline = strchr(currMessage, '\n');
if (newline == 0)
...deal with no newline in the current messages...
trimIndex = newline - currMessage;
Add this code just before the malloc() call:
// we need the destination buffer to be large enough for the '\f' character, plus
// the remaining string, plus the null terminator
printf("Allocating: %d Need: %d\n", (msgSize - trimIndex - 1), 1 + strlen(&currMessage[trimIndex+1]) + 1);
And I think it will show you the problem.
It's been demonstrated time and again that hand calculating buffer sizes can be error prone. Sometimes you have to do it, but other times you can let a function handle those error prone aspects:
// e.g.: "\fProgram started\r\nHow are you?\r".
char *trimMessage = strdup( &currMessage[trimIndex]);
if (trimMessage && (trimMessage[0] == '\n')) {
trimMessage[0] = '\f';
}
If your runtime doesn't have strdup(), it's easy enough to implement (http://snipplr.com/view/16919/strdup/).
And as a final edit, here's an alternative, simplified trimMessage() that I believe to be equivalent:
void trimMessage()
{
char *newline = strchr(currMessage, '\n');
if (!newline) return;
memmove( currMessage, newline, strlen(newline) + 1);
currMessage[0] = '\f'; // replace '\n'
messageCount--;
}

Resources