【问题标题】:check string lifetime duration检查字符串生存期
【发布时间】:2018-06-30 20:18:31
【问题描述】:

我目前想知道当只有指向字符串的指针已知时,是否可以检查 C 字符串是否具有静态生命周期。

基本上我想实现这样一个功能:

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

结果应该是这样的:

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

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

有没有可移植的方式来实现这样的功能?

PS:我希望这样的问题还没有被问到,我真的不知道要搜索什么。我的标题没有给我任何结果。

【问题讨论】:

  • 不,你为什么需要这个?
  • 你问的是C还是C++?
  • 写入只读内存中的字符串应该引发异常,您可以捕获并忽略它(我认为)。但是编译器不会编译它,因为你的字符串被声明为const,所以你必须依次覆盖它。它也不是可移植的:它依赖于目标操作系统能够构造只读段,以及编译器将这些字符串写入一个。
  • @HolyBlackCat:如果字符串在只读内存中,写入字符串将触发错误。 AFAIK 两种语言 C 和 C++ 本身都没有关于字符串(或其他信息)的元信息,除了它们可以声明为 const 或不声明。哪个(再次 AFAIK)你不能在运行时 test

标签: c string lifetime


【解决方案1】:

不可能以便携或可靠的方式进行。

但是,指向静态和只读内存的指针通常位于与堆栈和动态分配的内存不同的内存段中,因此您可以检查指针和一些预分配的样本指针之间的差异,以及猜测内存布局。

#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 PC 上的结果:

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

请永远不要在生产中使用此代码。

【讨论】:

  • 为什么要将readonlyFossilizedBirdBones - str 的差异转换为intabs()。似乎imaxabs() 最有可能避免有符号整数溢出和/或截断。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 2020-06-23
  • 2014-06-06
  • 1970-01-01
  • 2023-03-14
  • 2015-08-26
相关资源
最近更新 更多