EXC_BAD_INSTRUCTION using "strcpy" within a function - c

When I use the whole code in the main function it works perfectly but now I want to use the function for some "Strings" which I initialize in a 2D-Array.
The idea behind the function is to create a product of a struct globally initialized. The line with strcpy gives the error:
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
I am using Xcode 11.3.1 on a Mac.
Can you guys help me with that?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
struct produkt neues_angebot(char *produktname);
struct produkt{
char name[5];
int produkt_zahl;
float produkt_preis;
};
struct produkt neues_angebot(char *produktname){
time_t t;
srand((unsigned) time(&t));
struct produkt Zwischenname = {
"xxx",(rand() % 49),((rand()% 600)/100)
};
strcpy(Zwischenname.name, produktname);
return Zwischenname;
}
int main(int argc, const char * argv[]) {
char teste[]="hello";
printf("%s\n",neues_angebot(teste).name);
}

Strings in C are null terminated. The string "hello" uses 6 bytes of storage: the 5 characters h e l l o plus the terminating null character.
Now strcpy does no length checking, so strcpy(Zwischenname.name, produktname) will attempt to copy all 6 of those bytes into the array Zwischenname.name, which only has space for 5 bytes. That overflows the array and is undefined behavior - the crash you observed is one of the many possible results.

The strcpy will copy the last character of teste, the null terminator '\0', to outside the bounds of the the destination buffer as it is one byte shorter than it needs to be, this will cause Zwischenname.name to not be null terminated.
The problem is printf will need the null-terminator to know where the string ends in order work correctly, passing a non null-terminated character array as an argument to printf("%s", argument); invokes undefined behavior.
Remember, in order for an array of characters to be treated as a propper string it needs to be null terminated, many library fuctions in C rely on this principle. Always make sure that it is.

Related

Uninitialized Condition Valgrind

After running the following C program with Valgrind, it says the packets.payload variable is uninitialised. But I cannot figure out why since I've already put "1234567890" in packets.payload
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct packet {
int payload_length;
char payload[10];
} packet_t;
int main () {
packet_t packet;
strncpy(packet.payload, "1234567890", 10);
puts(packet.payload);
}
A pointer to a string (a sequence of characters terminated by null-character) must be passed to puts().
Your packet.payload doesn't contain terminating null-character, so you cannot use it for puts().
You can use printf() with specifying length to print to print that:
printf("%.*s\n", 10, packet.payload);
packet_t packet ={0, "0000000"} is initialization. In the code, you are just assigning the value, not initialization. Initialization of a variable provides its initial value at the time of construction (definition).

C dynamic allocated array using memset for initialisation

So i've make a program about an char array that is dinamically allocated, the program is not yet finished but i've got some different return values after i run the program, no warnings, no errors in compiler so i don't know why i get this also sometimes the program crashes..
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main(){
int n,i;
char *tab=NULL;
printf("New size of array: ");
scanf("%d",&n);
tab=(char*)malloc(n*sizeof(char));
memset(tab,'X',n*sizeof(tab));
for(i=0;i<n;i++)
printf("%c",tab[i]);
free(tab);
return 0;
}
In your memset you write n * sizeof(tab), I think you wanted to write :
n * sizeof(char)
You can also add a +1 add the end of your malloc and check the return value, just for security.
The C library function void *memset(void *str, int c, size_t n) copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str.
memset(tab,'X',n*sizeof(char));
You've written n*sizeof(tab), you are copying the character X to unknown memory which might cause crash during runtime.
Look into this line:
memset(tab,'X',n*sizeof(tab));
You declared tab as a pointer, and a storage size of a pointer is more than one byte. Multiplying that by n which is the size of the array you want will cause you to copy data to memory space you're not allowed to access which is why you get a segmentation fault.
If you must use sizeof, then do this:
memset(tab,'X',n*sizeof(char));
or better yet, just do this:
memset(tab,'X',n);
because a char is one byte and n times 1 = n.

Reading data from an Ubuntu terminal and storing it in different variables in C

I am writing a program that stores information of the iwscan Ubuntu command. I am actually reading properly the file that is created with the information; however, when trying to store data(ESSID in a string, Channel in an int and Quality in a double), I have several problems treating the strings to extract the data...
The code is as following:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
char *tratarEssid(char *cadena);
int tratarCanal(char *cadena);
double tratarCalidad(char *cadena);
int tratarCanal(char *cadena){
char resultado[2];
strncpy(resultado,cadena+9,2);
int canal;
canal=atoi(resultado);
return canal;
}
double tratarCalidad(char *cadena){
char resultado[6];
strncpy(resultado,cadena+8,6);
char num[2];
char den[2];
strncpy(num,resultado,2);
if(strlen(resultado)==5)
strncpy(den,resultado+3,2);
else
strncpy(den,resultado+2,2);
double numerador=atof(num);
double denominador=atof(den);
double calidad=numerador/denominador;
return calidad;
}
char *tratarEssid(char *cadena){
char *essid;
essid=(char *)malloc(sizeof(char)*10);
strncpy(essid,cadena+7,10);
return essid;
}
int main(){
int i;
const char *CHECKCANAL = "Channel:";
const char *CHECKQUALITY = "Quality=";
const char *CHECKESSID = "ESSID:";
double calidad;
int canal;
char *essid;
char cadena[20];
system("iwlist wlan0 scan | egrep \"(Channel|Signal level|ESSID)\">/home/wein/Escritorio/basic/bin/Debug/Lista.txt");
printf("Lista hecha\n");
lista=fopen("Lista.txt","r");
printf("Lista abierta\n");
while (!feof(lista)){
fgets(cadena,20,lista);
printf("%s",cadena);
if (strncmp(CHECKCANAL,cadena,strlen(CHECKCANAL))==0){
canal=tratarCanal(cadena);
printf("CANAL: %d\n",canal);
}
else if (strncmp(CHECKQUALITY,cadena,strlen(CHECKCANAL))==0){
calidad=tratarCalidad(cadena);
printf("CALIDAD: %f",calidad);
}
else if(strncmp(CHECKESSID,cadena,strlen(CHECKESSID))==0){
essid=tratarEssid(cadena);
printf("ESSID: %s\n",essid);
}
}
return 0;
}
So I know that my problem is in the conditionals made to filterig and treating the useful strings, just I don't know why the strncmp doesn't work properly (It should compare the beginning of the line with content of the String, or that's the idea) and thus, the functions don't work properly (Maybe I messed up in the functions as well...). Is there any other chance for treating the strings I receive correctly??
The output of the printf of the char[] cadena is just like this
Channel:11
Frequency:2.462 GH
z (Channel 11)
Quality=57/70 Sig
nal level=-53 dBm
ESSID:"eduroam"
And I should be able to extract from there the ESSID, Quality and Channel.
Thanks for any idea/suggestion/help received.
use strtok() on cadena[] to divide the string into tokens as,
token[0]=strtok(cadena,"\n") //considering the output you gave each date is in newline
token[1]=strtok(NULL,"\n")
token[2]=strtok(NULL,"\n")
token[3]=strtok(NULL,"\n")
token[4]=strtok(NULL,"\n")
token[5]=strtok(NULL,"\n")
then use sscanf() to get the required data from the token as,
sscanf(token[5],"ESSID:%s",ESSID);
sscanf(token[3],"Quality=%d/%d",&q1,&q2 ) //quality=q1/q2
sscanf(token[0],"Channel:%d",&channel)
this will give the required values from the string cadena[].
Your strncpy function calls don't add the terminator to the strings you copy to. Besides, they are to small to contain the terminator.
That means that when you call functions such as atoi on an unterminated string it will cause undefined behavior, as the function continues beyond the end of the allocated memory.

strcmp giving segmentation fault [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 6 years ago.
this is my code giving segmentation fault
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(void) {
char *get;
scanf("%s", get);
int k = strcmp("sachin", get);
printf("%d", k);
}
thanks for any help;
char *get;
The above statement defines get to be a pointer to a character. It can store the address of an object of type char, not a character itself. The problem is with both scanf and strcmp call. You need to define an array of characters to store the input string.
#include <stdio.h>
#include <string.h>
int main(void) {
// assuming max string length 40
// +1 for the terminating null byte added by scanf
char get[40+1];
// "%40s" means write at most 40 characters
// into the buffer get and then add the null byte
// at the end. This is to guard against buffer overrun by
// scanf in case the input string is too large for get to store
scanf("%40s", get);
int k = strcmp("sachin", get);
printf("%d", k);
return 0;
}
You need to allocate memory for the pointer get.
Or use a char array:
char get[MAX_SIZE];
scanf("%s",get);
When you declare a pointer, it is not pointing to any memory address. You have to explicitly allocate memory for that pointer by malloc (c-style) or new (c++ style).
You will also need to manage the clean operation yourself by free / delete respectively.
of sure you get a segment fault.
you told your computer to write user input to uninitialized pointer.
char *get; // just a pointer that may wildly points anywhere
scanf("%s",get);
define get to be some char array
char get[SOME_LARGE_CONSTANTS_THAT_CLEARLY_IS_LARGER_THAN_YOUR_USER_INPUT];

Why does VS throw an error when compiling an uninitialized string used in a strcpy function?

I was curious to know why the following code snippet works in some C compilers and not others. My professor can compile this code in DevC++ and so can I, but I can not compile this code in VS 2010. Any ideas? VS says a.word has a bad pointer. I assume VS is mad because I haven't initialized a.word, but why does the code compile and work in DevC++? I have to add a.word=""; before the strcpy and then it works in VS, but again I am curious to know why. Thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct foo{ int num;
char* word;
struct foo *ptr;};
int main() {
struct foo a;
a.num = 5; a.ptr = &a;
strcpy(a.word,"whichword");
}
a.word is an unitialized pointer (char*) not an uninitialized string (char[n]). This is quite different:
char buf[20]; /* Uninitialized string, backed by memory, */
char* s; /* but an unitialized `char*` is pointing to some random */
/* memory address. */
/* Any attempt to access it is undefined behaviour. */
I have to add a.word=""; before the strcpy and then it works in VS
This would also result in undefined behaviour as a.word is pointing at a string literal which is not permitted to be modified.
The only two solutions are to change word to be a fixed sized array or to dynamically allocate memory for word before copying. In either case the memory associated with word must be large enough to store the string being copied (plus the null terminating character).

Resources