【问题标题】:Is it possible to set environment variable through a makefile?是否可以通过makefile设置环境变量?
【发布时间】:2015-08-21 16:06:33
【问题描述】:

我想利用可以更改内存分配参数的 MALLOC_PERTURB_ 环境变量(man 3 mallopt)。但是,我想控制应用程序级别的分配参数,而不是整个系统级别。理想情况下,如果我可以通过项目的 makefile 控制它们。我尝试通过 makefile 更改提到的变量,但没有成功。

为了测试,我创建了这个 test.c 文件:

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

#define N 50

int main()
{
    char *chars;
    int i;

    if (NULL == (chars = malloc(N * sizeof(*chars))))
        return EXIT_FAILURE;

    free(chars);

    for (i = 0; i < N; ++i)
        printf("%c", chars[i]);
    printf("\n");

    return EXIT_SUCCESS;
}

是的,我知道我正在从释放的内存中读取,但这就是使用 MALLOC_PERTURB_ 的全部意义所在。

预期结果:50 个字符的 ASCII 字符,值为 MALLOC_PERTURB_。

足够接近:

$ export MALLOC_PERTURB_=97
$ gcc test.c -o test
$ ./test
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa��


$ export MALLOC_PERTURB_=105
$ gcc test.c -o test
$ ./test
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii��

然后我尝试将编译包含在makefile中,但没有成功。

导出变量 (as proposed here)

生成文件

all:
    export MALLOC_PERTURB_=110
    gcc test.c -o test

结果(我希望 110 有 'n' 个字母)

$ export MALLOC_PERTURB_=105
$ make
export MALLOC_PERTURB_=110
gcc test.c -o test 
$ ./test
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii��

递归调用 make (as proposed here)

生成文件

all:
    MALLOC_PERTURB_=110
    $(MAKE) rec

rec:
    gcc test.c -o test

结果(我希望 110 有 'n' 个字母)

$ export MALLOC_PERTURB_=105
$ make
MALLOC_PERTURB_=110
make rec
make[1]: Entering directory '~/test'
gcc test.c -o test
make[1]: Leaving directory '~/test'
$ ./test
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii��

我试图从 github 的包含 MALLOC_PERTURB_ 的 makefile 中找到任何灵感,但它们太复杂了,我无法理解。 一些例子:(1)、(2)、(3)

一些技术信息:

Linux 4.0.1-1-ARCH x86_64
gcc version 4.9.2 20150304 (prerelease) (GCC)
GNU Make 4.1

【问题讨论】:

  • 只是为了我的教化,这个表达式是什么:'sizeof(*chars)'试图完成? sizeof() 唯一知道的是 'char * chars' 的大小为(对于 32 位系统)为 4 并且取消引用指针为 1。这似乎是一种复杂的说 sizeof(char) 的方式,它始终为 1 并且malloc() 参数中永远不需要
  • 在第一个示例中,与您的问题相关的唯一行是:'.PHONY: test test: $(BIN)/gtest$(BASENAME) MALLOC_PERTURB_=21 MALLOC_CHECK_=2 LD_LIBRARY_PATH=$(LIB ) $(BIN)/gtest$(BASENAME)' 在调用 gtest... 程序之前设置了 2 个(临时)环境变量
  • 您可以在export 行之后添加分号和反斜杠,这样就可以了。就目前而言,make 创建一个运行export 的 shell,然后创建另一个 shell 来运行测试(因此第二个 shell 不知道导出的变量)。我的建议迫使make 将两条线视为一条线。还有一个指令可以添加到makefile,它告诉GNU make 在单个shell 中运行目标的所有操作;它被恰当地命名为.ONESHELL:。
  • @user3629249 考虑到 sizeof:我更喜欢使用 sizeof(*VARIABLE_NAME) 而不是 sizeof(VARIABLE_TYPE),因为它允许我快速安全地更改变量类型。这样我就不必在我的代码中搜索所有出现的 sizeof(VARIABLE_TYPE) 。有关更多信息,请参阅此问题的已接受答案:(stackoverflow.com/questions/373252/…)。

标签: c unix makefile malloc gnu-make


【解决方案1】:

在Bash中,可以在命令前指定环境变量,例如,

MALLOC_PERTURB_=105 gcc test.c -o test

或

MALLOC_PERTURB_=105 ./test

(我相信只有运行必须设置这个变量,而不是编译。)

由于您使用的是 Linux,因此 Make 很有可能使用 Bash 作为 shell,您可以将上面的行放在您的 makefile 中。

【讨论】:

  • 这不是 bash 特定的:任何 像 Bourne shell 一样的 shell 都会这样做。
【解决方案2】:

您也可以在编译时设置“MALLOC_PERTURB_”值,方法是将M_PERTURB 选项传递给mallopt() 函数(glibc 2.4 或更高版本)。详情请见http://man7.org/linux/man-pages/man3/mallopt.3.html。

因此,如果您希望您的程序在编译时合并环境变量“MALLOC_PERTURB_”的设置,那么这样的事情应该可以工作:

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

#include <malloc.h> // for mallopt() and M_PERTURB

#define N 50

int main()
{
    char *chars;
    int i;

#if MALLOC_PERTURB_
    mallopt( M_PERTURB, MALLOC_PERTURB_);
#endif

    if (NULL == (chars = malloc(N * sizeof(*chars))))
        return EXIT_FAILURE;

    free(chars);

    for (i = 0; i < N; ++i)
        printf("%c", chars[i]);
    printf("\n");

    return EXIT_SUCCESS;
}

然后让您的 makefile 将 MALLOC_PERTURB_ 值作为宏定义传递给编译器命令行(或您想要使用的任何机制):

gcc -DMALLOC_PERTURB_=97 test.c -o test

【讨论】:

    【解决方案3】:

    Browning,在 makefile 中设置环境变量很容易,您已经这样做了,但这不是您想要的。这使得它在编译期间采用该值。但是你希望它在你运行程序时改变 malloc 的行为。

    阅读您引用的手册页确认您需要在程序运行的环境中设置环境变量。同样阅读 cmets,已经提到设置环境变量的 makefile 仅针对测试程序这样做,它们实际上作为构建的一部分运行。

    你不希望它在 makefile 中。您希望在实际运行程序时设置它,这是其他 cmets 和答案告诉您如何做的。很抱歉接受了一个答案,但我需要更多的空间来解决这个问题,而且它就是你的答案。你已经知道该怎么做了。你只是不知道它到底是什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-06
      • 1970-01-01
      • 2012-03-26
      • 2015-02-01
      • 2016-04-28
      • 2013-10-28
      • 1970-01-01
      相关资源
      最近更新 更多