How do I return null if my string has no null terminator

this is my first time posting here so sorry if I'm doing something wrong.

I have a C programme that allocates a pool, then stores a char array, "Hello World", in memory and then retrieves it. One of the lines of the code in my main method reads:

store(pool, 50, sizeof(str) - 1, str);

(my store method variables are (Pool *pool, int offset, int size, void *object)

If I am reading this correctly, then the pool being allocated is 1 less than the string size, so cutting of the that would be on the end.

How do I check that character is missing off the end and return null because of it?

/* _POOL - pool 
 * int size - the size of the pool in bytes
 * void* ipPool - pointer to memory malloc'd by the operating system 
 */

typedef struct _POOL
{
    int size;
    void* memory;
} Pool;

/* Allocate a memory pool of size n bytes from system memory (i.e., via malloc()) 
 * and return a pointer to the filled data Pool structure */
Pool* allocatePool(int n)
{
    if(n <= 0)
    {
            return NULL;
    }

    Pool *pool = malloc(sizeof *pool);

    if(!pool)
    {
            return NULL;
    }

    pool->size = n;

    if(!(pool->memory = malloc(n)))
    {
            return NULL;
    }

    return pool;
};

/* Free a memory pool allocated through allocatePool(int) */
void freePool(Pool *pool)
{
    if(!pool)
    {
             return;
    }

    if(pool->memory)
    {
            free(pool->memory);
    }

    free(pool);
};

/* Store an arbitrary object of size n bytes at
 * location offset within the pool */
void store(Pool *pool, int offset, int size, void *object)
{
    if(!pool)
    {
            return;
    }

    if(size + offset > pool->size)
    {
            return;
    }

    memcpy(pool + offset, object, size);
};

/* Retrieve an arbitrary object of size n bytes 
 * from a location offset within the pool */
void *retrieve(Pool *pool, int offset, int size)
{
    if(!pool)
    {
            return NULL;
    }

    void *obj = malloc(size);

    if(!obj)
    {
            return NULL;
    }

    if(size + offset > pool->size)
    {
            return NULL;
    }

    return memcpy(obj,  pool + offset, size);
};

void main()
{
    const int poolSize = 500;
    Pool* pool;
    int x = 5;
    char c = 'c';
    char str[] = "Hello World";

    /* Should retrieve Hello World */
    store(pool, 8, sizeof(str), str);
    printf("Test 4: Store an arbitrary multi-byte valuen");
    printf("tStored: %sn", str);
    printf("tRetrieves: %sn", (char*)retrieve(pool, 8, sizeof(str)));

    /* Should retrieve null */
    store(pool, 50, sizeof(str) - 1, str);
    printf("Test 5: Store an arbitrary multi-byte value with no null terminatorn");
    printf("tStored: %sn", str);
    printf("tRetrieves: %sn", (char*)retrieve(pool, 50, sizeof(str) - 1));
};

is all the code that I think is involved. This is currently putting in Hello World and retrieving Hello World.

I cannot edit any of the main method, only the contents of the functions and the struct.


If you removed the trailing null character, you erased the only info that encoded the string´s length. There is no way to query the size of the block allocated.

This is because the terminating zero is C´s way of encoding the string length. Other languages´ runtimes use different methods, like storing the string length (as a byte, or word) in the very first byte pointed to by the string-referencing variable (Delphi for example).

So there is no way to detect if the trailing null is missing or not. If it is there, you can search for it. If it is not there, your search will inevitably access memory locations behind the last byte of the string, and fail to work correctly.

And because this search (or scan) for the null character is exactly what strlen is doing, you cannot use strlen , of course.


This shows how to test if there is a string terminator.

In the first case str is automatically sized and the '' terminator included.

In the second case xyz the array size has been defined so there is no room for any terminator.

#include <stdio.h>

char *pool(char *str, size_t size)
{
    size_t i;
    for(i=0; i<size; i++) {
        if(str[i] == '') {
            return str;
        }
    }
    return NULL;
}

int main(void)
{
    char str[] = "Hello World";
    char xyz[11] = "Hello World";

    if(pool(str, sizeof str) == NULL) {
        printf("No terminatorn");
    }
    else {
        printf("'%s' is good!n", str);
    }

    if(pool(xyz, sizeof xyz) == NULL) {
        printf("No terminatorn");
    }
    else {
        printf("'%s' is good!n", xyz);
    }
    return 0;
}

Program output:

'Hello World' is good!
No terminator

Since the memory pool is a freeform pool, it's kind of their own fault if they take off the returning null character. However, since you're simply copying the object in retrieve , you can add an extra null terminator yourself:

void *obj = malloc(size + 1);
*((char*)(obj) + size) = 0; // add the null character

With this in place, even if your end user decides to take off a null terminator, one will eventually appear, and it will usually appear in the correct location and thus never cause endless traversal errors that would exist otherwise if there was no null terminator.

链接地址: http://www.djcxy.com/p/72176.html

上一篇: 为什么pthreads的条件变量函数需要互斥锁?

下一篇: 如果我的字符串没有空终止符,如何返回null