首页 \ 问答 \ 检查Groovy版本Gradle正在使用(Checking Groovy version Gradle is using)

检查Groovy版本Gradle正在使用(Checking Groovy version Gradle is using)

我正在运行gradle,之前一直在运行groovy 1.76。 我现在更新到我的本地机器groovy(groovy_home指向groovy 2.1.2等)。

$ groovy -version
Groovy Version: 2.1.2 JVM: 1.7.0_17 Vendor: Oracle Corporation OS: Linux

然而,当我运行gradle命令(gradle test,classes等)时,我认为它不是针对groovy 2.1.2构建的,而实际上仍然是针对1.76构建的。 (我相信这个的原因是,当我执行这些类时,我不断收到此错误升级Groovy 1.7 - 2.1不兼容性 ,这与1.76后发生的更改有关)

有没有一种方法可以确认我的Gradle安装的哪个版本的Groovy正在构建?

另外,任何人都可以确认我应该配置Groovy的Groovy版本吗?


I am running gradle and have previously been running groovy 1.76. I have now updated to groovy on my local machine (groovy_home points to groovy 2.1.2 etc).

$ groovy -version
Groovy Version: 2.1.2 JVM: 1.7.0_17 Vendor: Oracle Corporation OS: Linux

However, when I am running gradle commands (gradle test, classes, etc) I believe it is not building against groovy 2.1.2 but is actually still building against 1.76. (The reason I believe this, is that when I execute the classes I keep getting this error Upgrading Groovy 1.7 - 2.1 Incompatability, which is related to changes made post 1.76)

Is there a way to confirm which version of groovy my gradle install is building against?

Also, can anyone confirm where I should be configuring the groovy version for gradle?


原文:https://stackoverflow.com/questions/16527384
更新时间:2023-07-05 11:07

最满意答案

首先,您没有使用未使用的vector进行任何测试。 编译器是聪明的,并且-O2 gccclang都将上面的代码编译为空的main() (除了单个xor eax, eax以设置返回值。请参阅此处的程序集。此外,大多数vector的默认构造函数实现(包括gccclang )甚至不会分配任何东西 - 它会等到第一个元素被添加之后再进行昂贵的分配步骤。

要获得更具体的结果,请分配一个BIG向量(以便将其与噪声区分开)并将其传递给另一个转换单元中的方法(或在单独的.cpp文件中定义),如下所示:

#include <vector>

void sink(std::vector<int>& v);

int main() {
    std::vector<int> v(12345678);
    sink(v);
}

现在,当您检查程序集时,您会发现它实际上正在执行某些操作

因此,Valgrind报告的~72,000字节与您的std::vector<int> v无关,您可能会看到完全为空的main的相同数字。

问题和引用文献的想法仍然与该问题不同,我将在下面回答。

程序退出时, 所有内存通常都会释放回操作系统,操作系统会强制执行此操作,而不是标准库。 操作系统只是清理进程使用的所有资源,包括非共享内存分配。 当Valgrind提到“在退出时使用”时,它正在讨论此操作系统清理之前,因为这是您想要知道的,看看您是否忘记释放任何东西。

您不需要任何单独的过程。 它只是意味着Valgrind可以跟踪mallocfree调用以及其他一些标准分配例程,但是标准库可能会在需要malloc 最初调用malloc (或者operator new或某些等价物)的那些上面使用另一层,但是当内存由进程取消分配,它将内部保存在某个列表中,而不是调用相应的取消分配例程(例如free )。 在后续分配中,它将使用其列表中的内容而不是返回标准方法(如果列表已用尽,则必须调用标准例程)。 由于旧版本的C ++中std::allocator定义有些无用,因此没有大量使用,但它在更新的标准中有所改变。 最大的好处是(a)为容器使用线程局部的固定大小分配,因为所有包含的对象大小相同,并且(b)允许分配器在容器被销毁时释放一个操作中的所有内容而不是逐个元素释放。

你引用的文档有点令人困惑,因为它谈到(不)重新调整内存到操作系统 - 但它应该说“重新调整到标准分配例程”。 Valgrind不需要将内存返回到操作系统以将其视为已释放 - 它会挂钩所有标准例程并知道何时释放该级别。 标准例程本身大量“缓存”分配的内存,如上所述(这是常见的,不像分配器例程缓存,这是不常见的),因此如果Valgrind需要将内存返回到操作系统,那么报告“退出时分配的内存”将毫无用处。


How does the C++ library implementation achieve that?

It doesn't. The valgrind information is outdated, I don't think any modern C++ implementations do that.

Does it keep around a separate process in the background that handles all allocation requests from its standard templates, so that when the program exits (a.out here), the memory is not immediately given back to the OS?

No, you've misunderstood. The valgrind docs aren't talking about keeping memory around that outlives the process. It's just talking about keeping memory pools within the process so that memory allocated and then deallocated by the process is kept in a pool and reused (by the same process!) later, instead of calling free immediately. But nobody does that for std::allocator nowadays, because std::allocator needs to be general purpose and perform reasonably well in all scenarios, and a good malloc implementation should meet those needs anyway. It's also fairly easy for users to override the default system malloc with an alternative like tcmalloc or jemalloc, so if std::allocator just forwards to malloc then it gets all the benefits of that replacement malloc.

If so, when will it give back, and how can I check the process indeed exists? If not, what is the "magic" behind the scene?

All memory in a process is returned to the OS when the process exits. There is no magic.

But the allocation you're seeing has nothing to do with this anyway.

There is 71 KB allocated. Why this number?

The 72kb you're seeing is allocated by the C++ runtime for its "emergency exception-handling pool". This pool is used to be able to allocate exception objects (such as bad_alloc exceptions) even when malloc can no longer allocate anything. We pre-allocate at startup, so if malloc runs out of memory we can still throw bad_alloc exceptions.

The specific number comes from this code:

       // Allocate the arena - we could add a GLIBCXX_EH_ARENA_SIZE environment
       // to make this tunable.
       arena_size = (EMERGENCY_OBJ_SIZE * EMERGENCY_OBJ_COUNT
                     + EMERGENCY_OBJ_COUNT * sizeof (__cxa_dependent_exception));
       arena = (char *)malloc (arena_size);

See https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/libsupc%2B%2B/eh_alloc.cc;h=005c28dbb1146c28715ac69f013ae41e3492f992;hb=HEAD#l117

Newer versions of valgrind know about this emergency EH pool and call a special function to free it right before the process exits, so that you don't see in use at exit: 72,704 bytes in 1 blocks. This was done because too many people fail to understand that memory still in use (and still reachable) is not a leak, and people kept complaining about it. So now valgrind frees it, just to stop people complaining. When not running under valgrind the pool doesn't get freed, because doing so is unnecessary (the OS will reclaim it when the process exits anyway).

相关问答

更多
  • 首先,您没有使用未使用的vector进行任何测试。 编译器是聪明的,并且-O2 gcc和clang都将上面的代码编译为空的main() (除了单个xor eax, eax以设置返回值。请参阅此处的程序集。此外,大多数vector的默认构造函数实现(包括gcc和clang )甚至不会分配任何东西 - 它会等到第一个元素被添加之后再进行昂贵的分配步骤。 要获得更具体的结果,请分配一个BIG向量(以便将其与噪声区分开)并将其传递给另一个转换单元中的方法(或在单独的.cpp文件中定义),如下所示: #include ...
  • 是的,当您的程序退出时,操作系统将自动释放您没有释放的任何内存。 这意味着在任何时候调用exit()通常都是安全的,尽管您需要注意其他未自动释放的资源,例如Windows上的全局原子和命名管道等。 Yes, any memory you don't free will be automatically freed by the operating system when your program exits. This means it's generally safe to call exit() at ...
  • 为什么分配内存是必要的? 因此,您将内存标记为您的内存。 没有其他人可以使用它。 它还验证实际上有可用内存。 如果你的系统只有1000字节的内存,那么选择字节1500来存储一些数据是一个坏主意。 如果我们使用内存而不分配它会发生什么? 没人知道。 您写的地址可能不存在。 可能已经开始使用其他进程,因此您将覆盖其数据。 记忆可以得到保护; 例如,在前一种情况下,操作系统可能会注意到您正在访问另一个进程已声明的内存,并阻止您。 您可能拥有该内存区域,但程序的另一部分由于某种原因正在使用它,并且您已经覆盖了自己的 ...
  • 我的懒惰...... 这是80 * 60 * 5 (Hz x秒x分钟)周期的结果: Process only:: mean: 0.00356445 in seconds Alloc Dealloc:: mean: 0.0743379 in seconds 这是代码和冗余输出: 分配 - 每次解除分配 class AllocEvery { public: int doSomething() { double pi, gold, ogh; std::strin ...
  • 只要您使用内存分配运行时链接到共享的MSVC库,这就可以工作。 然后EXE和DLL共享同一个堆。 如果您破坏了此依赖关系,则将不再共享堆,并且删除不同堆中的对象将破坏应用程序。 That works as long as you link to shared MSVC libraries with the memory allocation runtime. Then EXE and DLL share the same heap. If you break this dependency, the hea ...
  • 我强烈建议进行分配的模块也负责进行解除分配。 从而: int *ptr = module1->getIntData(); ... module1->freeIntData(ptr); 这允许不同的模块毫无困难地使用不同的分配器(malloc / free,new / delete,slab allocator等)。 在Posix系统上,进程中只能有一个malloc (和free )实现,所以如果getIntData的定义是“返回一个必须free释放的指针”,那么你getIntData了。 另一方面,我认为 ...
  • 这在很大程度上取决于您的编译器和openmp库实现。 我用gcc -fopenmp版本4.4.6(GCC)和libgomp 1.0.0尝试了你的代码,我也得到了尚未解除分配的堆块。 据我所知, libgomp并没有在执行结束时杀死它的衍生线程并使内核清理干净。 ==85122== HEAP SUMMARY: ==85122== in use at exit: 2,072 bytes in 4 blocks ==85122== total heap usage: 203 allocs, 199 f ...
  • 你应该使用new char而不是new char*来分配,因为new char*会分配那么多的指针。 这导致您从*frameBuffer =删除*意味着不会更改调用者的frameBuffer参数。 将行更改为 *framebuffer = new char[sizeof(Pixel) * width *height]; You should allocate using new char not new char* as new char* will allocate that many pointers ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。