I am trying to convert string from 'ascii' to 'utf-8', the 'lencoded_str' function will take a pointer char and return another pointer char. the input pointer char size is unknown, and it will change each time the 'lencoded_str' function called. my problem is the 'lencoded_str' function always return nothing.
Any help would be much appreciated.
this is just an example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
char *lencoded_str(char *in_str){
iconv_t iconv_obj = iconv_open("utf-8","ascii");
char *out_str = calloc(strlen(in_str) * 2, sizeof(char));
char *out_str_start = out_str;
size_t in_str_bytes_left = strlen(in_str);
size_t out_str_bytes_left = strlen(in_str) * 2;
int iconv_return = iconv(iconv_obj, &in_str, &in_str_bytes_left, &out_str, &out_str_bytes_left);
iconv_close(iconv_obj);
return out_str;
}
int main( ){
printf("out: %s\n", lencoded_str("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
printf("out: %s\n", lencoded_str("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
printf("out: %s\n", lencoded_str("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
}
iconv advances toe input and output string pointers so that they point at the end of the converted string.
That means you must save the original value of the char buffer and return it. You've already had the right idea with out_str_start, but you don't use it:
return out_str_start;
By using the return value from lencoded_str directly in printf and not storing it, you will leak the memory that yopu calloced. You could also go easy on the strlens; you only need to call it once.
Related
I am trying to read a file line by line, and get each line as a charĀ * to a dynamic string, the code I am using used to work and without changing it (or noticing it), it has ceased to work, accsesing the reed information results in an error. Here is a MRE of my code for getting one line:
#include <stdio.h>
#include <string.h>
#define MAX_STR_SIZE 10000
int main(void)
{
char* filePath; // is set by other working part of program to a real readable file address.
while (fgetc(filePath) != EOF) // an extra chracter is in the data files to account for this cheack.
{
char tempStr[MAX_STR_SIZE] = { 0 };
char* str = NULL;
fgets(tempStr, MAX_STR_SIZE, filePath);
tempStr[strcspn(tempStr, "\n")] = 0;
str = malloc(sizeof(char) * (strlen(tempStr) + 1)); // does not work
strcpy(str, tempStr);
}
}
The error:
Exception thrown at 0x00007ff95448d215 in GifProject.exe: Access violation writing location 0xFFFFFFFFEA1854F0.
It is difficult to diagnose your problem without a complete compilable program that exhibits the problem, but from the code fragment and the debugging information in the image, it seems you do not include <stdlib.h> and the prototype inferred by the compiler for malloc() from the actual argument is int malloc(size_t), leading to undefined behavior when you store the return value into the pointer str: because of the missing prototype, the compiler generates code that converts the return value from int to char *, sign extending from 32-bit to 64-bits, producing a meaningless pointer.
Note that you should also test the return value of fgets to properly handle end of file, and you should test for potential malloc failure before calling strcpy or better: use strdup that allocates and copies a string in a single call.
Here is a modified version:
#include <stdlib.h>
#include <string.h>
#define MAX_STR_SIZE 4096
char *readline(FILE *file) {
char tempStr[MAX_STR_SIZE];
if (!fgets(tempStr, sizeof tempStr, file)) {
/* end of file: return a null pointer */
return NULL;
}
/* strip the trailing newline if any */
tempStr[strcspn(tempStr, "\n")] = '\0';
/* allocate a copy of the string and return it */
return strdup(tempStr);
}
I'm trying to do very basic examples to understand how void pointers work. Here's an example I've written for having a void* string and casting it to its "working" type and printing some aspects of it:
int main(int argc, char *argv[]) {
// Create a void pointer which "acts like" a string
void * string = "hello";
// "Cast" the string so it's easier to work with
char * string_cast = (char*) string;
// Print the string and a character in it
printf("The string is: %s\n", string_cast);
printf("The third character is: %c\n", string_cast[2]);
// How to now do something like:
// (1) void pointer_to_string_obj = ?
// (2) cast that pointer_to_string_obj to a normal string
// (3) print the string like it would normally be done
}
Could someone please show an example of manually creating a string pointer of type *(char**) and why that type would need to be created in the first place (why not just a normal char*?). I apologize if my question is broad, but basically I'm trying to figure out various void pointer types and where I'm at now in my very beginner understanding, it's a bit confusing, and so seeing a few examples would be very helpful.
So I thought up a kind of a good example of double void pointer (that is, void**). One way to cut down on double-free bugs is to always set pointers to NULL after freeing them.
We could do so like so (questionable style):
myprojectinclude.h:
/* must happen after any standard headers */
void freep(void **pointer);
#define free(p) error_call_freep_instead p /* so that free doesn't exist anymore */
freep.c:
#include <stdlib.h>
#include "myprojectinclude.h"
#undef free
void freep(void **p)
{
if (p) {
free(*p);
*p = NULL;
}
}
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "myprojectinclude.h"
int main()
{
char *buffer = malloc(2048);
size_t buffer_size = 2048;
/* ... lots of code involving reading lines, etc. */
freep(&buffer);
/* buffer is guaranteed to be NULL here */
}
With this setup, double free is impossible. If we do
freep(&buffer);
freep(&buffer);
nothing goes wrong because buffer is NULL after the first call. (Note that passing NULL to free is safe; else we would add a NULL check like I had to do decades ago.)
This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 3 years ago.
I'm learning pointers in C, using Linux. I'm trying to use the strcat function, but it doesn't work and I don't understand why.
I'm passing a username to the main as an argument because I need to concatenate and put a number 1 in the first position of this username. For example if the I got as argument username123 I need to convert this to 1username123
I got this code:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char *finalUser;
userTemp = argv[1]; //I got the argument passed from terminal
finalUser = "1";
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
The code compiles, but I got a segmentation fault error and doesn't know why. Can you please help me going to the right direction?
It is undefined behaviour in C to attempt to modify a string literal (like "1"). Often, these are stored in non-modifiable memory to allow for certain optimisations.
Let's leave aside for the moment the fact that your entire program can be replaced with:
#include <stdio.h>
int main(int argc, char *argv[]){
printf("User: 1%s\n", (argc > 1) ? argv[1] : "");
return 0;
}
The way you ensure you have enough space is to create a buffer big enough to hold whatever you want to do. For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
// Check args provded.
if (argc < 2) {
puts("User: 1");
return 0;
}
// Allocate enough memory ('1' + arg + '\0') and check it worked.
char *buff = malloc(strlen(argv[1]) + 2);
if (buff == NULL) {
fprintf(stderr, "No memory\n");
return 1;
}
// Place data into memory and print.
strcpy(buff, "1");
strcat(buff, argv[1]);
printf("User: %s\n", buff);
// Free memory and return.
free(buff);
return 0;
}
What you shouldn't do is to allocate a fixed size buffer and blindly copy in the data provided by a user. That's how the vast majority of security problems occur, by people overwriting buffers with unexpected data.
I'm trying to use the strcat function, but it doesn't work and I don't understand why.
For starters, you really shouldn't use strcat(). Use strlcat() instead. The "l" version of this and other functions take an extra parameter that let you tell the function how large the destination buffer is, so that the function can avoid writing past the end of the buffer. strcat() doesn't have that parameter, so it relies on you to make sure the buffer is large enough to contain both strings. This is a common source of security problems in C code. The "l" version also makes sure that the resulting string is null-terminated.
The code compiles, but I got a segmentation fault error and doesn't know why.
Here's the prototype for the function: char *strcat( char *dest, const char *src );
Now, you're calling that essentially like this: strcat("1", someString);. That is, you're trying to append someString to "1", which is a string constant. There's no extra room in "1" for whatever string is in someString, and because you're using a function that will happily write past the end of the destination buffer, your code is effectively writing over whatever happens to be in memory next to that string constant.
To fix the problem, you should:
Switch to strlcat().
Use malloc() or some other means to allocate a destination buffer large enough to hold both strings.
Unlike in other languages there is no real string type in C.
You want this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char finalUser[100]; // finalUser can contain at most 99 characters
userTemp = argv[1]; //I got the argument passed from terminal
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
or even simpler:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
char finalUser[100]; // finalUser can contain at most 99 characters
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, argv[1]); //To concatenate argv[1] to finalUser
printf("User: %s\n",finalUser);
return 0;
}
Disclaimer: for the sake of brevity this code contains a fixed size buffer and no check for buffer overflow is done here.
The chapter dealing with strings in your C text book should cover this.
BTW you also should check if the program is invoked with an argument:
int main(int argc, char *arg[]){
if (argc != 2)
{
printf("you need to provide a command line argument\n");
return 1;
}
...
You're missing some fundamentals about C.
finalUser = "1";
This is created in "read-only" memory. You cannot mutate this. The first argument of strcat requires memory allocated for mutation, e.g.
char finalUser[32];
finalUser[0] = '1';
I have a simple C code as below :
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>
#include <math.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
#include <tchar.h>
int main()
{
int ndsc;
char *line = ' ';
FILE *fd;
int x;
wchar_t path[256];
wcscpy(path, L"C:/");
//wcscat(path, L"common\\descr.txt", wcslen(L"common\\descr.txt"));
//Previous
wcscat(path, L"common/descr.txt");
if ((fd = _wfopen(path, L"r")) == NULL)
{
printf("Can't open %s for reading.\n", path);
return 1;
}
for (ndsc = 0; fgetws((wchar_t*)line, 80, fd) != NULL; ndsc++)
{
x = wcslen((const wchar_t*)line);
printf("Length of %d line is %d\n", ndsc, x);
}
fclose(fd);
return 0;
}
I am trying to read a file called descr.txt from C:\Common directory. But in for loop it throws unhandled exception as below :
Can anybody explain me why I am getting this error and how to resolve.
By the way this code is being used in an .arx file of AutoCad. I just extracted the part which is throwing error and tried to run it as a standalone project in VS 2015 Update 3. This code is a part of .C file being called by from .NET. Even when executing in the context of .arx ( From AutoCad Clicking on the desired menu ) got the same exception.
Thanks in Advance.
Here: char *line = ' '; You assign a char to a char *.
Later you try to use a wide string buffer. You need wchar_t line[80] to actually allocate space for 80 wchar_t.
The variable line is a pointer, it points to the address 32 (using ASCII encoding).
That address is hardly a valid address to write a string of input.
You need to make it point to some memory big enough to fit the whole string you read (including the terminator). Or have it be an array.
Since the pointer is incorrect you will have undefined behavior, which makes your whole program ill-formed and invalid.
Furthermore, that you need to cast it in the call to fgetsw is another sign of you doing something wrong, and that is using the wrong type (char instead of wchar_t).
Line is a pointer to some illegal address casted from int value of ascii code of ' '.
instead of char *line = ' ';
make it (if you want line to be an array of chars)
char line[80 * sizeof(wchar_t)];
You arre trying to assign a char to a char * by using simple quotes.
If you want to directly assign an int or a char to a char *, use double quotes (" "), or, if it is a single char, you might want to proceed as follows:
char line[0] = ' ';
Make sure that your pointer has been malloc'd and it should do the trick.
A string of digits can later be re-converted to an int using atoi() if you want.
I wrote a function that will take a char* representing a binary number, and add one to that number. I've encountered a very confusing error, which is that the function works fine and dandy when the char* comes from user input when calling the function (a.k.a. argv[1]), but gives me a Bus error: 10 when I instead initialize the variable internally and pass it to the same function. I'm not sure what's behind this, so I turn to you guys. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void addOneBinaryMain(char* strBiNum, int index)
{
if (strBiNum[index] == '0' || index == 0) { //BUS ERROR OCCURS HERE
strBiNum[index] = '1';
return;
} else {
strBiNum[index] = '0';
addOneBinaryMain(strBiNum, index - 1);
}
}
void addOneBinary(char* strBiNum)
{
addOneBinaryMain(strBiNum, strlen(strBiNum)-1);
}
int main(int argc, char* argv[]) {
char* str = argv[1];
char* strZero = "00000000";
int i;
printf("%s\n", str);
printf("%s\n", strZero);
addOneBinary(str);
printf("added one to input string: %s\n", str); //succeeds
addOneBinary(strZero);
printf("added one to internal zero string: %s\n", strZero);
return 0;
}
Following around the error with print statements, it seems that it occurs in the addOneBinaryMain function (the recursive step), at the point I've marked.
strZero points at a constant string, that cannot be changed
strZero is just a point initialized with the address of your literal string "000000". This literal string is stored at a place in the application's ram that is read only (If i remember correctly think it's called static store).
Try declaring a char array on the stack or on the heap and copying strZero to it using strcpy.