通过makefile设置环境变量是否可能?

3

我想利用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_的全部意义。

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

足够接近:

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


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

我尝试将编译过程放在makefile中,但未成功。

导出变量(如此处所建议)

Makefile

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

结果(我期望110个字母,但实际上不是)

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

递归调用make命令 (如此处所提出的)

Makefile

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的Makefile中寻找包含MALLOC_PERTURB_的灵感,但它们对我来说太复杂了无法理解。 以下是一些例子:(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()参数中使用的复杂方式。 - user3629249
1
在第一个示例中,与您的问题相关的唯一行是:'.PHONY: test test: $(BIN)/gtest$(BASENAME) MALLOC_PERTURB_=21 MALLOC_CHECK_=2 LD_LIBRARY_PATH=$(LIB) $(BIN)/gtest$(BASENAME)',其中在调用gtest...程序之前设置了2个(临时)环境变量。 - user3629249
你可以在export行后面加上分号和反斜杠,它就会起作用。目前为止,make创建了一个运行export的shell,然后创建另一个shell来运行测试(因此第二个shell不知道导出的变量)。我建议的是强制make将这两行视为一行。还有一个指令,你可以添加到makefile中,告诉GNU make在单个shell中运行目标的所有操作;它的名称是.ONESHELL: - Jonathan Leffler
@user3629249 关于sizeof:我更倾向于使用sizeof(*VARIABLE_NAME)而不是sizeof(VARIABLE_TYPE),因为它使我能够快速和安全地更改变量类型。这样,我就不必在代码中搜索所有出现的sizeof(VARIABLE_TYPE)。请参阅此问题的被接受答案:(https://dev59.com/yXRC5IYBdhLWcg3wOOP1)以获取更多信息。 - browning0
3个回答

5
在Bash中,你可以在命令前指定环境变量,例如:
MALLOC_PERTURB_=105 gcc test.c -o test

或者

MALLOC_PERTURB_=105 ./test

我认为只有在运行时需要设置这个变量,而不是编译时。

由于您使用的是Linux系统,make命令很可能会使用Bash作为shell,因此您可以将上面的那一行代码放入您的makefile中。


3
这并不特定于Bash:任何行为类似于Bourne shell的Shell都会这样。 - Thomas Dickey

2
您可以通过向mallopt()函数传递M_PERTURB选项来在编译时设置"MALLOC_PERTURB_"的值(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

2
在makefile中设置环境变量很容易,而且您已经这样做了,但这不是您想要的。这会在编译时使用该值。但是您希望在运行程序时更改malloc的行为。
阅读您引用的man页面可以确认,您需要在运行程序的环境中设置环境变量。同时阅读评论,已经提到设置环境变量的makefile仅针对测试程序进行设置,并将其作为构建的一部分实际运行。
您不想将其放在makefile中。您希望在实际运行程序时设置它,这正是其他评论和答案告诉您如何做的。很抱歉占用了一个答案,但我需要更多的空间来澄清这一点,而且这就是答案,对于您来说。您已经知道如何做了。您只是不知道它是什么,确切地说。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接