Xcode Exc_BAD_ACCESS - c

so this code is giving me the Exc_bad_access_code(2) error and i have no idea why. I think the problem is with the parameters but im not sure, any thoughts?
#include <stdio.h>
void swap(char *x, char *y);
/* Function to swap values at two pointers */
void swap(char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
int main(int argc, const char * argv[]) {
// insert code here...
char *a = "ASD123";
swap (a+1 , a+2);
return 0;
}

You need to post the complete crash log to be sure, but it's probably that you are attempting to manipulate a string constant:
char *a = "ASD123";
swap (a+1 , a+2);
which probably lives in read-only memory.
Try:
char a[12];
strcpy(a, "ASD123");
swap (a+1 , a+2);
or:
char a[] = "ASD123";
swap (a+1 , a+2);
That will copy the string onto the stack, where it may be modified without issue. You could also use strdup() to copy the string onto the heap (don't forget to call free() to release the allocated memory).

You are trying to modify a string literal.
Change
char *a = "ASD123";
to
char a[] = "ASD123";
and your program will work.
In the first case a is simply a pointer pointing to a string literal which is in a write protected part of the memory on most platforms, hence the crash because you try to write info write protected memory.
In the second case a is a char array of length 7 which is initialized with "ASD123" (6 chars for the string and one char for the terminating zero).

You need to initialize a correctly. Something like char a[7] = "ASD123";
char* a only creates a pointer-to-char, it does not allocate enough memory to store the characters.

Related

How I can make a string array interchange it's components with a swap function?

The problem is that this code won't interchange these 2 strings. I'm new to programming but I can tell that the problem is that swap function, but I do not know how to fix it.
I tried to add strcpy instead of "=" in swap but that didn't worked.
#include <stdio.h>
#include <stdlib.h>
void swap(char *t1, char *t2) {
char *t;
t=t1;
t1=t2;
t2=t;
}
int main() {
char *s[2] = {"Hello", "World"};
swap(s[0], s[1]);
printf("%s\n%s", s[0], s[1]);
return 0;
}
You want to use out parameters here, and since your strings are represented as pointers, you need pointers to pointers:
void swap(char **t1, char **t2) {
char *t;
t = *t1;
*t1 = *t2;
*t2 = t;
}
Call it like this:
swap(&s[0], &s[1]);
I tried to add strcpy instead of "=" in swap but that didn't worked.
The reason why that doesn't work is because the strings are actually stored in the program's binary and therefore can't be modified, and with strcpy you would write over them. If you copy them to the stack or the heap instead then you can do the swap with strcpy. Of course that's going to be less efficient than just swapping the pointers, but this is how it would look like:
void swap(char *t1, char *t2) {
char buf[16]; // needs to be big enough to fit the string
strcpy(buf, t1);
strcpy(t1, t2);
strcpy(t2, buf);
}
Also you would need to change the definition of s to something akin to
char s[2][16] = { "Hello", "World" }; // strings are copied to the stack now
Check the types carefully.
What you have got as array members are pointers (to the starting element of string literals). You need to swap the members in a way so that they point to the other string literal. So, you need to change those pointers themselves.
So, you need to pass pointer to those pointers and then make the change from the called function.
Do something like
swap(&(s[0]), &(s[1]));
and then, in the called function:
void ptrSwap(char **t1, char **t2) {
char *temp;
temp=*t1;
*t1=*t2;
*t2=temp;
}
Bonus points: Name your functions (and variables, too, wherever applicable) meaningfully.
You need to passing the pointer of pointer, i.e. address of the position in array where the strings are present, so that you can swap and place correct addresses there.
Try the below code:
#include <stdio.h>
#include <stdlib.h>
void swap(char **t1, char **t2) {
char *t;
t=*t1;
*t1=*t2;
*t2=t;
}
int main() {
char *s[2] = {"Hello", "World"};
swap(&s[0], &s[1]);
printf("%s\n%s", s[0], s[1]);
return 0;
}
Output:
World
Hello

Passing pointer and copy value

I guess I do something stupid here, please help me understand what it is, i get a crash :
char *data="xyz";
int EEIndex=0;
int getEEPROMindex();
void updateEEPROMindex();
void getCmd(char *cmd);
void getcmdAtIndex(int index,char *cmd);
int main(int argc, const char * argv[]) {
getCmd(data);
printf("%s ",data );
return 0 ;
}
void getCmd(char *cmd)
{
getcmdAtIndex(EEIndex, cmd);
}
void getcmdAtIndex(int index,char *cmd)
{
char *EEPROM[]={"A","E","C","D"};
strcpy(cmd, EEPROM[index]);
EEIndex=index+1;
}
It's customary to make string literals read-only. That is:
char *data="xyz";
when your code tried to change the bytes x, y and z, the OS crashes it.
To make it writable, replace a pointer with an array; you should also specify the size of the array. The easiest method to do it is:
char data[] = "xyz"; // will hold a maximum of 3 bytes (size is implicit)
or
char data[20]; // will hold a maximum of 19 bytes plus an end-of-string byte
You can also use strdup:
char* data;
...
strdup(cmd, EEPROM[index]); // instead of strcpy
but this involves dynamic memory allocation, which I think you don't want to bother with.
You're strcpying into static memory space, i.e.
char *data="xyz";
That is, you created a string xyz that was stored in a reserved memory location at compile-time. You can't write into that memory location. You want to allocate new space, e.g. malloc.
char *data="xyz"; defines a char pointer to "xyz" which is located in read-only area so you can't write to this place. What point you still persist?
Change it to char data[] = "xyz" ensures this literal is copied to stack - so it's modifiable.
In addition, getcmdAtIndex function is not safe. What about out of index position?

Swapping elements of a char array works but swapping elements of a char string leads to core dump

I am trying to perform swap operation as shown in below program, but it seems to crash when I am copying the element b into a (line 3 in swap() method) - this happens if the input is a char string i.e, char *str; If it is a character array instead (as in char str[];) the swap operation works fine.
#include<stdio.h>
void swap(char *a, char *b)
{
char tmp;
tmp = *a;
*a = *b; /* crash occurs here */
*b = tmp;
}
void func(char *a)
{
swap(a+1, a+2);
}
int main()
{
char *str = "abc";
// char str[] = "abc"; /* with this char array, the above swap func works */
func(str);
}
I think this is related to some C string rules that I seem to be unaware of. Please help!
String literals are read-only, trying to modify a string literal leads to undefined behavior.
Simplest solution? Declare it as an array instead:
char str[] = "abc";
char *str = "abc";
Above puts the string in the constant data section (also known as .rdata) of the program.As this is treated as constant data, it can not be modified
char str[] = "abc";
Above puts the string in the stack area of the program, as declared inside the function scope.This data can be modified.
As this is about the storage of string data, you are getting Crash in first declaration.
'char *str = "abc";'
The above places the abc in read only memory. So it cannot be modified.
'char str[]="abc";' is placed in stack. so it can be modified.

Swap strings using strcpy

I am trying to swap two strings by using only pointer notation, (no arrays), with
a function that looks like this
void str_switch(char *a, char *b)
the swapping should work irrespective of the sizes of b and a, and it is not known.
my idea is this:
void str_switch(char *a, char *b) {
const char *temp = a;
strcpy(b, temp);
}
however, after this, I am not sure how to copy b to a, because b changes, I tried declaring other constant pointers, but once I change b, I can never get the old version.
This strays from your question, heading in particular as strcpy is not used, and follow your comment to Martin James:
void str_switch(char **a, char **b) {
char *tmp = *a;
*a = *b;
*b = tmp;
}
If you really want to use strcpy you'll have to know size of C-strings.
if your strings are stored in allocated memories using functions like malloc(); thus this code works perfectly for that case, especially as it treats strings with different size and length
#include <stdio.h> // list of libraries that need to be included
#include <stdlib.h>
#include <string.h>
void str_switch(char **a, char **b) {
if (strlen(*a)>strlen(*b)) // check the strings with lowest size to reallocate
{ // in order to fit the big one
char *temp=malloc((strlen(*a)+1)*sizeof(char)); // temp variable to preserve the lowest
// the variable with lowest length
strcpy(temp,*a); // store the longest string in its new location
strcpy(*a,*b);
free(*b); // free the allocated memory as we no longer need it
*b=temp; // assign the new address location for the lowest string
}
else if (strlen(*b)>strlen(*a)) // the same as above but invert a to b and b to a
{
char *temp=malloc((strlen(*b)+1)*sizeof(char));
strcpy(temp,*b);
strcpy(*b,*a);
free(*a);
*a=temp;
}
else // if the lengths are equal ==> #Morpfh solution
{
char *tmp = *a;
*a = *b;
*b = tmp;
}
}
This is a test for function above (main code)
int main(int argc, char *argv[])
{
char *a=malloc(sizeof(char)*6);
strcpy(a,"hello");
char *b=malloc(sizeof(char)*4);
strcpy(b,"bye");
printf("a=%s\nb=%s\n",a,b);
str_switch(&a,&b);
printf("----------------------\n");
printf("a=%s\nb=%s\n",a,b);
return 0;
}
and we get
a=hello
b=bye
----------------------
a=bye
b=hello
If you don't want to allocate extra storage, you would need to switch the strings by swapping one character at a time.
If you are OK allocating extra storage, strdup a, strcpy b into a, strcpy the copy of a into b, then free the copy.

C programming strcat using pointer

I am a beginner in C. I wanted to make strcat function using pointers. I made it but don't know what is wrong with it. I used gcc compiler and it gave segmentation fault output.
#include<stdio.h>
#include<string.h>
char scat(char *,char *);
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
while(*q!='\0') printf("the concatenated string is %c",*q);
}
char *scat(char *s,char *t)
{
char *p=s;
while(*p!='\0'){
p++;
}
while(*t!='\0'){
*p=*t;
p++;
t++;
}
return p-s-t;
}
This one works:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *scat(char *,char *); /* 1: your prototype was wrong */
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
printf("cat: %s\n", q); /* 2: you can use %s to print a string */
free(q);
}
char *scat(char *s,char *t)
{
char *p=malloc(strlen(s)+strlen(t)+1); /* 3: you will have to reserve memory to hold the copy. */
int ptr =0, temp = 0; /* 4 initialise some helpers */
while(s[temp]!='\0'){ /* 5. use the temp to "walk" over string 1 */
p[ptr++] = s[temp++];
}
temp=0;
while(t[temp]!='\0'){ /* and string two */
p[ptr++]=t[temp++];
}
return p;
}
You have to allocate new space to copy at the end of s. Otherwise, your while loo[ will go in memory you don't have access to.
You shoul learn about malloc() here.
It is undefined behaviour to modify a string literal and s, and eventually p, is pointing to a string literal:
char* s = "james";
s is passed as first argument to scat() to which the local char* p is assigned and then:
*p=*t;
which on first invocation is attempting to overwite the null character an the end of the string literal "james".
A possible solution would be to use malloc() to allocate a buffer large enough to contain the concatentation of the two input strings:
char* result = malloc(strlen(s) + strlen(p) + 1); /* + 1 for null terminator. */
and copy them into it. The caller must remember to free() the returned char*.
You may find the list of frequently asked pointer questions useful.
Because p goes till the end of the string and then it starts advancing to illegal memory.
That is why you get segmentation fault.
It's because s points to "james\0", string literal & you cannot modify constant.
Change char *s="james"; to char s[50]="james";.
You need to understand the basics of pointers.
a char * is not a string or array of characters, it's the address of the beginning of the data.
you can't do a char * - char* !!
This is a good tutorial to start with
you will have to use malloc
You get a segmentation fault because you move the pointer to the end of s and then just start writing the data of p to the memory directly following s. What makes you believe there is writable memory available after s? Any attempt to write data to non-writable memory results in a segmentation fault and it looks like the memory following s is not writable (which is to expect, since "string constants" are usually stored in read-only memory).
Several things look out of order.
First keep in mind that when you want to return a pointer to something created within a function it needs to have been malloc'ed somewhere. Much easier if you pass the destination as an argument to the function. If you follow the former approach, don't forget to free() it when you're done with it.
Also, the function scat has to return a pointer in the declaration i.e. char *scat, not char scat.
Finally you don't need that loop to print the string, printf("%s", string); will take care of printing the string for you (provided it's terminated).
At first, your code will be in infinte loop because of the below line. you were supposed to use curely braces by including "p++; t++ " statements.
while(*t!='\0')
*p=*t;
though you do like this, you are trying to alter the content of the string literal. which will result in undefined behavior like segmentation fault.
A sequence of characters enclosed with in double quotes are called as string literal. it is also called as "string". String is fixed in size. once you created, you can't extend its size and alter the contents. Doing so will lead to undefined behavior.
To solve this problem , you need to allocate a new character array whose size is sum of the length of two strings passed. then append the two strings into the new array. finally return the address of the new array.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* scat(char *,char *);
void append(char *t , char *s);
int main(void)
{
char *s="james";
char *t="bond";
char *n = scat(s,t);
printf("the concatenated string is %s",n);
return 0;
}
char* scat(char *s,char *t)
{
int len = strlen(s) + strlen(t);
char *tmp = (char *)malloc(sizeof(char)* len);
append(tmp,s);
append(tmp,t);
return tmp;
}
void append(char *t , char *s)
{
//move pointer t to end of the string it points.
while(*t != '\0'){
t++;
}
while( *s != '\0' ){
*t = *s;
t++;
s++;
}
}

Resources