проверить продолжительность жизни строки - PullRequest
0 голосов
/ 30 июня 2018

Мне сейчас интересно, можно ли проверить, имеет ли C-строка статическую продолжительность жизни или нет, если известен только указатель на строку.

В принципе, я хочу реализовать такую ​​функцию:

bool isStaticString(const char *str)
{
    //do magic stuff
}

и результаты должны быть такими:

 isStaticString("Hello World!"); //returns true

 char str[5] = {'\0'};
 isStaticString(str); //returns false

Есть ли какой-нибудь переносимый способ реализации такой функции?

PS: Надеюсь, такой вопрос еще не задавался, я не знал, что искать. Мой заголовок не дал мне никаких результатов.

1 Ответ

0 голосов
/ 01 июля 2018

Невозможно сделать портативным или надежным способом.

Однако указатели на статическую и доступную только для чтения память обычно находятся в разных сегментах памяти, чем стек и динамически выделенная память, поэтому вы можете проверить разницу между указателем и некоторым предварительно выделенным указателем выборки, а также предположить макет памяти.

#include <string>
#include <stdlib.h>
#include <stdio.h>

enum { CHAR_ARRAY_SIZE = 32 }; // Say no to magic constants

const char readonlyFossilizedBirdBones[CHAR_ARRAY_SIZE] = "Crow skeleton from taxidermist";
char globalVariableBirdBones[CHAR_ARRAY_SIZE] = "This pigeon was hit by a car";

bool askBirdBonesIfStringIsStatic(const char *str)
{
    char freshStackBirdBones[CHAR_ARRAY_SIZE] = "Chicken wings from trash bin";
    char * bloodyAllocBirdBones = (char *) malloc(CHAR_ARRAY_SIZE);
    // strcpy() is unsafe, and strncpy() does not always zero-terminate the result
    // but snprintf() is safe and will not trigger any static code analysis tools
    snprintf(bloodyAllocBirdBones, CHAR_ARRAY_SIZE, "%s", "Sparrow caught by your cat");
    bool divinationSaysStatic =
        abs(readonlyFossilizedBirdBones - str) < abs(freshStackBirdBones - str) &&
        abs(readonlyFossilizedBirdBones - str) < abs(bloodyAllocBirdBones - str) &&
        abs(globalVariableBirdBones - str) < abs(freshStackBirdBones - str) &&
        abs(globalVariableBirdBones - str) < abs(bloodyAllocBirdBones - str);
    printf("Asking bird bones about '%s' at %p:\n", str, str);
    printf("Comparing to readonly %p global %p stack %p alloc %p\n",
            readonlyFossilizedBirdBones, globalVariableBirdBones,
            freshStackBirdBones, bloodyAllocBirdBones);
    printf("Result is %s\n\n", divinationSaysStatic ? "favorable" : "unfavorable");
    free(bloodyAllocBirdBones);
    return divinationSaysStatic;
}

int main()
{
    static char s1[CHAR_ARRAY_SIZE] = "Static string";
    char s2[CHAR_ARRAY_SIZE] = "Short-lived stack string";
    char * s3 = (char *) malloc(CHAR_ARRAY_SIZE);
    snprintf(s3, CHAR_ARRAY_SIZE, "%s", "String allocated by malloc()");
    askBirdBonesIfStringIsStatic(s1);
    askBirdBonesIfStringIsStatic(s2);
    askBirdBonesIfStringIsStatic(s3);
    free(s3);
    return 0;
}

И результаты на моем 64-битном ПК с Linux:

Asking bird bones about 'Static string' at 0x560815f27080:
Comparing to readonly 0x560815d26b00 global 0x560815f27060 stack 0x7ffe741d0b90 alloc 0x560816365c50
Result is favorable

Asking bird bones about 'Short-lived stack string' at 0x7ffe741d0be0:
Comparing to readonly 0x560815d26b00 global 0x560815f27060 stack 0x7ffe741d0b90 alloc 0x560816365c50
Result is unfavorable

Asking bird bones about 'String allocated by malloc()' at 0x560816365c20:
Comparing to readonly 0x560815d26b00 global 0x560815f27060 stack 0x7ffe741d0b90 alloc 0x560816365c50
Result is unfavorable

Пожалуйста, никогда не используйте этот код в производстве.

...