Imagine having this code and you don't really know what to except in the pointer of char (a string terminated or an array of chars (string not terminated)), is possibile to use strlen function on a safe way that handle not terminated string? (prevent overflows if the input is not a string terminanted) or can you fix it only by knowing the size of what you pass in input? so the function will become foo(char *c, size_t MAXSIZE)?
void foo(char *c) {
a = strlen(c);
}
We never know what really is behind a pointer. It could also only be a pointer to a single character.
Even by passing a size, you could imagine someone passing a bad pointer and an unrelated value.
C is not a safe language, it does not have runtime type checks. You can do anything you want, you can't prevent others from doing anything they want with your functions.
It's not safe to use just strlen if it's not a null-terminated byte string. According to cppreference:
The behavior is undefined if str is not a pointer to a null-terminated byte string.
If you want to cover the case of not null-terminated byte string then you should use the size_t strnlen_s( const char *str, size_t strsz ), which works just like normal strlen with the exception:
that the function returns zero if str is a null pointer and returns strsz if the null character was not found in the first strsz bytes of str.
It is not possible unless you pass the size.
You can avoid crashing, at least - by asking the operating system how much readable memory there is at this address. (Windows: call VirtualQuery. Linux: read /proc/self/maps). But it's not helpful. There can be lots of readable memory after your string that's totally unrelated to your string but just happened to get allocated after it. Finding out how much memory is safe to read doesn't tell you how long the string is.
To check if the buffer contains a null terminator within a maximum number of characters, the memchr function can be used. The following function safe_strlen behaves like the strlen_s function defined by Annex K of the C specification, and uses memchr to find the position of the first (if any) null terminator in the buffer.
#include <stdint.h>
#include <string.h>
/**
* Get the length of a possibly null terminated string, clamped to a maximum.
*
* If \p s is not NULL, searches up to \p maxsize bytes from \p s to find the
* first null terminator, if any.
*
* \param s Start of string.
* \param maxsize Maximum number of bytes to search.
*
* \return 0 if \p s is \c NULL.
* \return \p maxsize if null terminator not found.
* \return length of null terminated string if null terminator found.
*/
size_t safe_strlen(const char *s, size_t maxsize)
{
size_t length = 0;
if (s)
{
#if PTRDIFF_MAX < SIZE_MAX
/* May need to search the buffer in chunks. */
while (maxsize)
#endif
{
const char *e;
size_t pos;
#if PTRDIFF_MAX < SIZE_MAX
if (maxsize > PTRDIFF_MAX)
{
/* Limit size of chunk. */
pos = PTRDIFF_MAX;
}
else
#endif
{
/* This is the final chunk. */
pos = maxsize;
}
/* Search for null terminator in chunk. */
e = memchr(s, 0, pos);
if (e) {
/* Null terminator found. */
pos = e - s; /* position of null terminator in chunk */
#if PTRDIFF_MAX < SIZE_MAX
/* Make this the final chunk. */
maxsize = pos;
#endif
}
/* Update returned length. */
length += pos;
#if PTRDIFF_MAX < SIZE_MAX
/* Advance to next chunk. */
s += pos;
maxsize -= pos;
#endif
}
}
return length;
}
The code is complicated by the necessity to deal with buffer sizes larger than PTRDIFF_MAX if PTRDIFF_MAX is less than SIZE_MAX. The core functionality without the extra safety checks is as follows:
/* less safe version of the above - may result in undefined behavior. */
size_t less_safe_strlen(const char *s, size_t maxsize)
{
size_t length = 0;
if (s)
{
const char *e = memchr(s, 0, maxsize);
if (e)
{
length = e - s;
}
else
{
length = maxsize;
}
}
return length;
}
Related
While searching through this board for information about reading a full file into memory using C, I came across a use of fread() that I haven't seen before. I'm trying to understand it.
My questions are:
Is there a name/term for what is being done here?
What is happening when the size_t used is being added to the char *data and how is this considered a valid void *ptr by fread?
I'm going to put the code from the author's post in here and I'll link to the post as well. Unfortunately, the post is old, locked, and I don't have enough points here to leave a comment asking for clarification on it.
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
/* Size of each input chunk to be
read and allocate for. */
#ifndef READALL_CHUNK
#define READALL_CHUNK 262144
#endif
#define READALL_OK 0 /* Success */
#define READALL_INVALID -1 /* Invalid parameters */
#define READALL_ERROR -2 /* Stream error */
#define READALL_TOOMUCH -3 /* Too much input */
#define READALL_NOMEM -4 /* Out of memory */
/* This function returns one of the READALL_ constants above.
If the return value is zero == READALL_OK, then:
(*dataptr) points to a dynamically allocated buffer, with
(*sizeptr) chars read from the file.
The buffer is allocated for one extra char, which is NUL,
and automatically appended after the data.
Initial values of (*dataptr) and (*sizeptr) are ignored.
*/
int readall(FILE *in, char **dataptr, size_t *sizeptr)
{
char *data = NULL, *temp;
size_t size = 0;
size_t used = 0;
size_t n;
/* None of the parameters can be NULL. */
if (in == NULL || dataptr == NULL || sizeptr == NULL)
return READALL_INVALID;
/* A read error already occurred? */
if (ferror(in))
return READALL_ERROR;
while (1) {
if (used + READALL_CHUNK + 1 > size) {
size = used + READALL_CHUNK + 1;
/* Overflow check. Some ANSI C compilers
may optimize this away, though. */
if (size <= used) {
free(data);
return READALL_TOOMUCH;
}
temp = realloc(data, size);
if (temp == NULL) {
free(data);
return READALL_NOMEM;
}
data = temp;
}
n = fread(data + used, 1, READALL_CHUNK, in);
if (n == 0)
break;
used += n;
}
if (ferror(in)) {
free(data);
return READALL_ERROR;
}
temp = realloc(data, used + 1);
if (temp == NULL) {
free(data);
return READALL_NOMEM;
}
data = temp;
data[used] = '\0';
*dataptr = data;
*sizeptr = used;
return READALL_OK;
}
Link: C Programming: How to read the whole file contents into a buffer
What is happening when the size_t used is being added to the char *data and how is this considered a valid void *ptr by fread?
In practice(*), a pointer is just a number, which references an address in (virtual) memory. What's being done here is simple pointer arithmetic: You can add an integer to a pointer, which increases its value, so if your pointer pointed to address 1000 and you add 20, it now points to address 1020. Since used is always the number of bytes read so far, you point this many bytes into the data buffer.
But there's one more thing: This only works as described if the data type of the pointer has a size of 1 byte (as char does(*)). Because when you do pointer arithmetic, you don't increase the pointer by that many bytes, but really by multiples of the data type's size, so you always end up pointing to the start of an element in your array, and not somewhere in the middle if you're dealing with int. I.e. if you have int *x which points to address 1000, and you do x += 20, then x will point to address 1080 now, which is where x[20] would be located.
and how is this considered a valid void *ptr by fread?
Considering "pointers are just numbers", fread doesn't care how you arrived at that pointer value. As long as there is valid memory to write to, it will happily accept whatever you pass it.
(*) Assuming a modern architecture accessible by mere mortals.
They are similar functions, but what is the exact difference between them? The Linux documentation states:
Note: Use kmemdup_nul() instead if the size is known exactly.
Both functions allocate the needed memory through kmalloc() and then place a NUL terminator at the end of the allocated buffer. The only difference between the two is that kstrndup() first calls strnlen() to calculate the length of the string and therefore the needed size, thus scanning the string.
You can see kmemdup_nul() as an optimized version of kstrndup(). If you already know the length of the string, you can avoid the initial scanning and just use kmemdup_nul() passing in the length as argument. This saves time since the string doesn't need to be scanned, and it's the reason why you see that note.
Moreover, kstrndup() saves space if the string is shorter than max, so in case you don't know the length of the string, even though kmemdup_nul() would work as well, you might want to call kstrndup() instead to potentially save space.
You can clearly see from the code that the only difference between the two functions is the call to strnlen(). Here's the source code, from mm/util.c:
/**
* kstrndup - allocate space for and copy an existing string
* #s: the string to duplicate
* #max: read at most #max chars from #s
* #gfp: the GFP mask used in the kmalloc() call when allocating memory
*
* Note: Use kmemdup_nul() instead if the size is known exactly.
*
* Return: newly allocated copy of #s or %NULL in case of error
*/
char *kstrndup(const char *s, size_t max, gfp_t gfp)
{
size_t len;
char *buf;
if (!s)
return NULL;
len = strnlen(s, max);
buf = kmalloc_track_caller(len+1, gfp);
if (buf) {
memcpy(buf, s, len);
buf[len] = '\0';
}
return buf;
}
EXPORT_SYMBOL(kstrndup);
/**
* kmemdup_nul - Create a NUL-terminated string from unterminated data
* #s: The data to stringify
* #len: The size of the data
* #gfp: the GFP mask used in the kmalloc() call when allocating memory
*
* Return: newly allocated copy of #s with NUL-termination or %NULL in
* case of error
*/
char *kmemdup_nul(const char *s, size_t len, gfp_t gfp)
{
char *buf;
if (!s)
return NULL;
buf = kmalloc_track_caller(len + 1, gfp);
if (buf) {
memcpy(buf, s, len);
buf[len] = '\0';
}
return buf;
}
EXPORT_SYMBOL(kmemdup_nul);
I have the following code in C now
int length = 50
char *target_str = (char*) malloc(length);
char *source_str = read_string_from_somewhere() // read a string from somewhere
// with length, say 20
memcpy(target_str, source_str, length);
The scenario is that target_str is initialized with 50 bytes. source_str is a string of length 20.
If I want to copy the source_str to target_str i use memcpy() as above with length 50, which is the size of target_str. The reason I use length in memcpy is that, the source_str can have a max value of length but is usually less than that (in the above example its 20).
Now, if I want to copy till length of source_str based on its terminating character ('\0'), even if memcpy length is more than the index of terminating character, is the above code a right way to do it? or is there an alternative suggestion.
Thanks for any help.
The scenario is that target_str is initialized with 50 bytes. source_str is a string of length 20.
If I want to copy the source_str to target_str i use memcpy() as above with length 50, which is the size of target_str.
currently you ask for memcpy to read 30 characters after the end of the source string because it does not care of a possible null terminator on the source, this is an undefined behavior
because you copy a string you can use strcpy rather than memcpy
but the problem of size can be reversed, I mean the target can be smaller than the source, and without protection you will have again a undefined behavior
so you can use strncpy giving the length of the target, just take care of the necessity to add a final null character in case the target is smaller than the source :
int length = 50
char *target_str = (char*) malloc(length);
char *source_str = read_string_from_somewhere(); // length unknown
strncpy(target_str, source_str, length - 1); // -1 to let place for \0
target_str[length - 1] = 0; // force the presence of a null character at end in case
If I want to copy the source_str to target_str i use memcpy() as above
with length 50, which is the size of target_str. The reason I use
length in memcpy is that, the source_str can have a max value of
length but is usually less than that (in the above example its 20).
It is crucially important to distinguish between
the size of the array to which source_str points, and
the length of the string, if any, to which source_str points (+/- the terminator).
If source_str is certain to point to an array of length 50 or more then the memcpy() approach you present is ok. If not, then it produces undefined behavior when source_str in fact points to a shorter array. Any result within the power of your C implementation may occur.
If source_str is certain to point to a (properly-terminated) C string of no more than length - 1 characters, and if it is its string value that you want to copy, then strcpy() is more natural than memcpy(). It will copy all the string contents, up to and including the terminator. This presents no problem when source_str points to an array shorter than length, so long as it contains a string terminator.
If neither of those cases is certain to hold, then it's not clear what you want to do. The strncpy() function may cover some of those cases, but it does not cover all of them.
Now, if I want to copy till length of source_str based on its terminating character ('\0'), even if memcpy length is more than the index of terminating character, is the above code a right way to do it?
No; you'd be copying the entire content of source_str, even past the null-terminator if it occurs before the end of the allocated space for the string it is pointing to.
If your concern is minimizing the auxiliary space used by your program, what you could do is use strlen to determine the length of source_str, and allocate target_str based on that. Also, strcpy is similar to memcpy but is specifically intended for null-terminated strings (observe that it has no "size" or "length" parameter):
char *target_str = NULL;
char *source_str = read_string_from_somewhere();
size_t len = strlen(source_str);
target_str = malloc(len + 1);
strcpy(target_str, source_str);
// ...
free(target_str);
target_str = NULL;
memcpy is used to copy fixed blocks of memory, so if you want to copy something shorter that is terminated by '\n' you don't want to use memcpy.
There is other functions like strncpy or strlcpy that do similar things.
Best to check what the implementations do. I removed the optimized versions from the original source code for the sake of readability.
This is an example memcpy implementation: https://git.musl-libc.org/cgit/musl/tree/src/string/memcpy.c
void *memcpy(void *restrict dest, const void *restrict src, size_t n)
{
unsigned char *d = dest;
const unsigned char *s = src;
for (; n; n--) *d++ = *s++;
return dest;
}
It's clear that here, both pieces of memory are visited for n times. regardless of the size of source or destination string, which causes copying of memory past your string if it was shorter. Which is bad and can cause various unwanted behavior.
this is strlcpy from: https://git.musl-libc.org/cgit/musl/tree/src/string/strlcpy.c
size_t strlcpy(char *d, const char *s, size_t n)
{
char *d0 = d;
size_t *wd;
if (!n--) goto finish;
for (; n && (*d=*s); n--, s++, d++);
*d = 0;
finish:
return d-d0 + strlen(s);
}
The trick here is that n && (*d = 0) evaluates to false and will break the looping condition and exit early.
Hence this gives you the wanted behaviour.
Use strlen to determine the exact size of source_string and allocate accordingly, remembering to add an extra byte for the null terminator. Here's a full example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *source_str = "string_read_from_somewhere";
int len = strlen(source_str);
char *target_str = malloc(len + 1);
if (!target_str) {
fprintf(stderr, "%s:%d: malloc failed", __FILE__, __LINE__);
return 1;
}
memcpy(target_str, source_str, len + 1);
puts(target_str);
free(target_str);
return 0;
}
Also, there's no need to cast the result of malloc. Don't forget to free the allocated memory.
As mentioned in the comments, you probably want to restrict the size of the malloced string to a sensible amount.
I want to create a program that copies, element by element, one char array to another but the problem is that, if I don´t introduce in the destination array the null character, the program outputs the correct String + weird characters, so my solution was to iterate through with the length of the String + 1 in order to include the null character, is there any way to iterate with the length of the String without having to worry about the null character? The code is as follows:
int copy(char * source, char * destination, unsigned int lengthDestination);
int copy(char * source, char * destination, unsigned int lengthDestination)
{
int i;
for(i = 0; source[i] != '\0'; i++) {
//Count the length of the source array
}
if(i + 1 != lengthDestination){ //i + 1 in order to take into account '\0'
return 1;
}
for(int j = 0; j < lengthDestination; j++) {
destination[j] = source[j];
}
return 0;
}
int main() {
char * source = "Test number 17"; //Length is 15 counting the null character
unsigned int destinationLength = 15;
char destination[destinationLength];
copy(source, destination, destinationLength);
printf("The String source is: %s\n", source);
printf("The String destination is: %s\n", destination);
return 0;
}
You will always need to 'worry' about the null terminator, in the sense that you can't not have a null terminator in your destination C string, and you will always need to explicitly write the null terminator at the end of your new C string.
Even the built-in strcpy method will copy the null terminator character from your original string to the destination string.
#include <stdio.h>
#include <assert.h>
int copy(char * source, char * destination, unsigned int lengthDestination);
int copy(char * source, char * destination, unsigned int lengthDestination)
{
int i;
for(i = 0; source[i] != '\0'; i++) {
destination[i] = source[i];
}
assert(i+1 == lengthDestination);
destination[i+1] = '\0';
return 0;
}
int main() {
char * source = "Test number 17"; //Length is 15 counting the null character
unsigned int destinationLength = 15;
char destination[destinationLength];
copy(source, destination, destinationLength);
printf("The String source is: %s\n", source);
printf("The String destination is: %s\n", destination);
return 0;
}
If you are passing destination previously declared with automatic storage type or as a pointer previously allocated with malloc, calloc or realloc having allocated storage type, and in either case having nchars of storage available, you can implement a fairly robust copy function by simply using snprintf.
Since you are passing the maximum number of characters, including the nul-terminating character as a parameter to your copy function, that dovetails nicely with the size parameter for snprintf. Further, snprintf will insure a nul-terminated string in destination -- even if source is too long to fit in destination. As a benefit, snprintf returns the number of characters copied if there is sufficient storage in destination for source, otherwise it returns the number of characters that would have been copied had destination had sufficient space -- allowing you to determine the number of characters truncated if destination is insufficient to hold your source string.
Before looking at the implementation of copy let's look at a prototype and talk about declaring functions to that they provide a meaningful return, and while up to you, let's also look at the order of parameters and type qualifier for source, e.g.
/* simple strcpy src to dest, returns dest on success and number of chars
* (including nul-termining char) in nchar, returns NULL otherwise.
*/
char *copy (char *dest, const char *src, size_t *nchar);
If you notice, most string functions return a pointer to the destination string on success (or NULL otherwise) which allows you to make immediate use of the return. Next, while not a show-stopper, most string (or memory in general) copy functions place the destination as the first parameter, followed later by the source. I'm sure either Brian Kerrigan or Dennis Ritchie could explain why, but suffice it to say, most copy function parameters are ordered that way.
Notice also that since you are not modifying the source string in copy, it is best to qualify the parameter as const. The const qualifier is more or less a promise you make to the compiler that source will not be modified in copy which allows the compiler to warn if it sees you breaking that promise, while also allowing the compiler to further optimize the function knowing source will not change.
Finally notice your size or my nchar is passed as a pointer above instead of an immediate value. Since a function in C can only return a single value, if you need a way to get a second piece of information back to the caller, pass a pointer as a parameter so the value at that address can be updated within the function making the new value available to the calling function. Here you return a pointer to dest (or NULL) to indicate success/failure while also updating nchar to contain the number of characters in dest (including the nul-terminating character as you passed in a size not a length).
The definition of copy is quite short and simplistic. The only requirement is the source and destination strings not overlap. (neither strcpy or snprintf are defined in that case). The basic flow is to validate both src and dest are not NULL, then handle the case where src is the "empty-string" (e.g. 1st character is the nul-character) and then to copy src to dest using snprintf saving the return in written and then using a simple conditional to determine whether truncation occurred (and warning in that case) and concluding by updating the value pointed to by nchar and returning dest, e.g.
/* simple strcpy src to dest, returns dest on success and number of chars
* (including nul-termining char) in nchar, returns NULL otherwise.
*/
char *copy (char *dest, const char *src, size_t *nchar)
{
if (!src || !dest) { /* validate src & dest not NULL */
fputs ("error: src or dest NULL\n", stderr);
return NULL; /* return NULL on error */
}
if (!*src) /* handle src being an "empty-string" */
*dest = 0, *nchar = 0;
int written = snprintf (dest, *nchar, "%s", src); /* call snprintf */
if ((size_t)written + 1 > *nchar) { /* handle truncated case */
fprintf (stderr, "warning: dest truncated by %zu chars.\n",
(size_t)(written + 1) - *nchar); /* warn with count */
}
else /* src fit in dest, set nchar to no. of chars in dest */
*nchar = (size_t)(written + 1); /* including nul-character */
return dest; /* return dest so available for immediate use */
}
Putting it altogether in a short example that takes the string to copy as the first argument to the program (using "source string" by default if no argument is given), you could do something like the following:
#include <stdio.h>
#define MAXC 16 /* constant for destination length */
/* simple strcpy src to dest, returns dest on success and number of chars
* (including nul-termining char) in nchar, returns NULL otherwise.
*/
char *copy (char *dest, const char *src, size_t *nchar)
{
if (!src || !dest) { /* validate src & dest not NULL */
fputs ("error: src or dest NULL\n", stderr);
return NULL; /* return NULL on error */
}
if (!*src) /* handle src being an "empty-string" */
*dest = 0, *nchar = 0;
int written = snprintf (dest, *nchar, "%s", src); /* call snprintf */
if ((size_t)written + 1 > *nchar) { /* handle truncated case */
fprintf (stderr, "warning: dest truncated by %zu chars.\n",
(size_t)(written + 1) - *nchar); /* warn with count */
}
else /* src fit in dest, set nchar to no. of chars in dest */
*nchar = (size_t)(written + 1); /* including nul-character */
return dest; /* return dest so available for immediate use */
}
int main (int argc, char **argv) {
char *src = argc > 1 ? argv[1] : "source string",
dest[MAXC];
size_t n = MAXC;
if (copy (dest, src, &n))
printf ("dest: '%s' (%zu chars including nul-char)\n", dest, n);
}
(note: the maximum number of characters in dest is kept short intentionally to easily show how truncation is handled -- size as appropriate for your needs)
Example Use/Output
$ ./bin/strcpy_snprintf
dest: 'source string' (14 chars including nul-char)
Showing maximum number of characters that can be copied without warning:
$ ./bin/strcpy_snprintf 123456789012345
dest: '123456789012345' (16 chars including nul-char)
Showing handling source too long for destination:
$ ./bin/strcpy_snprintf 1234567890123456
warning: dest truncated by 1 chars.
dest: '123456789012345' (16 chars including nul-char)
Look things over and let me know if you have further questions. There are at least a dozen different ways to approach a string copy, but given you are passing dest with its own storage and passing the maximum number of characters (including the nul-character) as a parameter, it's hard to beat snprintf in that case.
Easiest way:
char *copy(const char *source, char *destination, size_t lengthDestination)
{
memcpy(destination, source, lengthDestination -1);
destination[lengthDestination -1] = 0;
return destination;
}
I am trying to create a simple datastructure that will make it easy to convert back and forth between ASCII strings and Unicode strings. My issue is that the length returned by the function mbstowcs is correct but the length returned by the function wcslen, on the newly created wchar_t string, is not. Am I missing something here?
typedef struct{
wchar_t *string;
long length; // I have also tried int, and size_t
} String;
void setCString(String *obj, char *str){
obj->length = strlen(str);
free(obj->string); // Free original string
obj->string = (wchar_t *)malloc((obj->length + 1) * sizeof(wchar_t)); //Allocate space for new string to be copied to
//memset(obj->string,'\0',(obj->length + 1)); NOTE: I tried this but it doesn't make any difference
size_t length = 0;
length = mbstowcs(obj->string, (const char *)str, obj->length);
printf("Length = %d\n",(int)length); // Prints correct length
printf("!C string %s converted to wchar string %ls\n",str,obj->string); //obj->string is of a wcslen size larger than Length above...
if(length != wcslen(obj->string))
printf("Length failure!\n");
if(length == -1)
{
//Conversion failed, set string to NULL terminated character
free(obj->string);
obj->string = (wchar_t *)malloc(sizeof(wchar_t));
obj->string = L'\0';
}
else
{
//Conversion worked! but wcslen (and printf("%ls)) show the string is actually larger than length
//do stuff
}
}
The code seems to work fine for me. Can you provide more context, such as the content of strings you're passing to it, and what locale you're using?
A few other bugs/style issues I noticed:
obj->length is left as the allocated length, rather than updated to match the length in (wide) characters. Is that your intention?
The cast to const char * is useless and bad style.
Edit: Upon discussion, it looks like you may be using a nonconformant Windows version of the mbstowcs function. If so, your question should be updated to reflect as such.
Edit 2: The code only happened to work for me because malloc returned a fresh, zero-filled buffer. Since you are passing obj->length to mbstowcs as the maximum number of wchar_t values to write to the destination, it will run out of space and not be able to write the null terminator unless there's a proper multibyte character (one which requires more than a single byte) in the source string. Change this to obj->length+1 and it should work fine.
The length you need to pass to mbstowcs() includes the L'\0' terminator character, but your calculated length in obj->length() does not include it - you need to add 1 to the value passed to mbstowcs().
In addition, instead of using strlen(str) to determine the length of the converted string, you should be using mbstowcs(0, src, 0) + 1. You should also change the type of str to const char *, and elide the cast. realloc() can be used in place of a free() / malloc() pair. Overall, it should look like:
typedef struct {
wchar_t *string;
size_t length;
} String;
void setCString(String *obj, const char *str)
{
obj->length = mbstowcs(0, src, 0);
obj->string = realloc(obj->string, (obj->length + 1) * sizeof(wchar_t));
size_t length = mbstowcs(obj->string, str, obj->length + 1);
printf("Length = %zu\n", length);
printf("!C string %s converted to wchar string %ls\n", str, obj->string);
if (length != wcslen(obj->string))
printf("Length failure!\n");
if (length == (size_t)-1)
{
//Conversion failed, set string to NULL terminated character
obj->string = realloc(obj->string, sizeof(wchar_t));
obj->string = L'\0';
}
else
{
//Conversion worked!
//do stuff
}
}
Mark Benningfield points out that mbstowcs(0, src, 0) is a POSIX / XSI extension to the C standard - to obtain the required length under only standard C, you must instead use:
const char *src_copy = src;
obj->length = mbstowcs(NULL, &src_copy, 0, NULL);
I am running this on Ubuntu linux with UTF-8 as locale.
Here is the additional info as requested:
I am calling this function with a fully allocated structure and passing in a hard coded "string" (not a L"string"). so I call the function with what is essentially setCString(*obj, "Hello!").
Length = 6
!C string Hello! converted to wchar string Hello!xxxxxxxxxxxxxxxxxxxx
(where x = random data)
Length failure!
for reference
printf("wcslen = %d\n",(int)wcslen(obj->string)); prints out as
wcslen = 11