编译全攻略-编译器处理及LNK错误的解决方法

2023-12-11 19:08

本文主要是介绍编译全攻略-编译器处理及LNK错误的解决方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

预处理器-编译器-汇编器-链接器

  预处理器会处理相关的预处理指令,一般是以"#"开头的指令。如:#i nclude "xx.h" #define等。

  编译器把对应的*.cpp翻译成*.s文件(汇编语言)。 汇编器则处理*.s生成对应的*.o文件(obj目标文件)

  最后链接器把所有的*.o文件链接成一个可执行文件(?.exe)

  1.部件:

  首先要知道部件(可以暂且狭义地理解为一个类)一般分为头文件(我喜欢称为接口,如:*.h)及实现文件(如:*.cpp)。

  一般头文件会是放一些用来作声明的东东作为接口而存在的。而实现文件主要是实现的具体代码。

  2.编译单个文件:

  记住IDE在bulid文件时只编译实现文件(如*.cpp)来产生obj,在vc下你可以对某个?.cpp按下ctrl+f7单独编译它

  生成对应一个?.obj文件。在编译?.cpp时IDE会在?.cpp中按顺序处理用#i nclude包括进来的头文件

  (如果该头文件中又#i nclude有文件,同样会按顺序跟进处理各个头文件,如此递归。。)

  3.内部链接与外部链接:

  内、外链接是比较基础的东东,但是也是新手最容易错的地方,所以这里有必要祥细讨论一下。

  内部链接产生的符号只在本地?.obj中可见,而外部链接的符号是所有*.obj之间可见的。

  如:用inline的是内部链接,在文件头中直接声明的变量、不带inline的全局函数都是外部链接。

  在文件头中类的内部声明的函数(不带函数体)是外部链接,而带函数体一般会是内部链接(因为IDE会尽量把它作为内联函数)

  认识内部链接与外部链接有什么作用呢?下面用vc6举个例子:

  // 文件main.cpp内容:

  void main(){}

  // 文件t1.cpp内容:

  #i nclude "a.h"

  void Test1(){ Foo(); }

  // 文件t2.cpp内容:

  #i nclude "a.h"

  void Test2(){ Foo(); }

  // 文件a.h内容:

  void Foo( ){ }

  好,用vc生成一个空的console程序(File - new - projects - win32 console application),并关掉预编译选项开关

  (project - setting - Cagegoryrecompiled Headers - Not using precompiled headers)

  现在你打开t1.cpp按ctrl+f7编译生成t1.obj通过 打开t2.cpp按ctrl+f7编译生成t2.obj通过

  而当你链接时会发现:

  Linking...

  t2.obj : error LNK2005: "void __cdecl Foo(void)" (?Foo@@YAXXZ) already defined in t1.obj

  这是因为:

  1. 编译t1.cpp在处理到#i nclude "a.h"中的Foo时看到的Foo函数原型定义是外部链接的,所以在t1.obj中记录Foo符号是外部的。

  2. 编译t2.cpp在处理到#i nclude "a.h"中的Foo时看到的Foo函数原型定义是外部链接的,所以在t2.obj中记录Foo符号是外部的。

  3. 最后在链接 t1.obj 及 t2.obj 时, vc发现有两处地方(t1.obj和t2.obj中)定义了相同的外部符号(注意:是定义,外部符号可以多处声明但不可多处定义,因为外部符号是全局可见的,假设这时有t3.cpp声明用到了这个符号就不知道应该调用t1.obj中的还是t2.obj中的了),所以会报错。

  解决的办法有几种:

  a.将a.h中的定义改写为声明,而用另一个文件a.cpp来存放函数体。(提示:把上述程序改来试试)

  (函数体放在其它任何一个cpp中如t1.cpp也可以,不过良好的习惯是用对应cpp文件来存放)。

  这时包括a.h的文件除了a.obj中有函数体代码外,其它包括a.h的cpp生成的obj文件都只有对应的符号而没有函数体,如t1.obj、t2.obj就只有符号,当最后链接时IDE会把a.obj的Foo()函数体链接进exe文件中,并把t1.obj、t2.obj中的Foo符号转换成对应在函数体exe文件中的地址。

  另外:当变量放在a.h中会变成全局变量的定义,如何让它变为声明呢?

  例如: 我们在a.h中加入:class CFoo{};CFoo* obj;

  这时按f7进行build时出现:

  Linking...

  t2.obj : error LNK2005: "class CFoo * obj" (?obj@@3PAVCFoo@@A) already defined in t1.obj

  一个好办法就是在a.cpp中定义此变量( CFoo* obj,然后拷贝此定义到a.h文件中并在前面加上extern(extern CFoo* obj如此就可通过了。当然extern也可以在任何调用此变量的位置之前声明,不过强烈建议不要这么作,因为到处作用extern,会导致接口不统一。良好的习惯是接口一般就放到对应的头文件。

  b. 将a.h中的定义修改成内部链接,即加上inline关键字,这时每个t1.obj和t2.obj都存放有一份Foo函数体,但它们不是外部符号,所以不会被别的obj文件引用到,故不存在冲突。(提示:把上述程序改来试试)

  另外我作了个实验来验证”vc是把是否是外部符号的标志记录在obj文件中的“(有点绕口)。可以看看,如下:

  (1)文件内容:

  // 文件main.cpp内容:

  void main(){}

  // 文件t1.cpp内容:

  #i nclude "a.h"

  void Test1(){ Foo(); }

  // 文件t2.cpp内容:

  #i nclude "a.h"

  void Test2(){ Foo(); }

  // 文件a.h内容:

  inline void Foo( ){ }

  (2) 选t1.cpp按ctrl+f7单独编译,并把编译后的t1.obj修改成t1.obj_inline

  (3) 选t2.cpp按ctrl+f7单独编译,并把编译后的t2.obj修改成t2.obj_inline

  (4) 把除了t1.obj_inline及t2.obj_inline外的其它编译生成的文件删除。

  (5) 修改a.h内容为:void Foo( ){ },使之变为非内联函数作测试

  (6) rebuild all所有文件。这时提示:

  Linking...

  t2.obj : error LNK2005: "void __cdecl Foo(void)" (?Foo@@YAXXZ) already defined in t1.obj

Debug/cle.exe : fatal error LNK1169: one or more multiply defined symbols found

  (7) 好,看看工程目录下的debug目录中会看到新生成的obj文件。

  下面我们来手工链接看看,

  打开菜单中的project - setting - Link,拷贝Project options下的所有内容,如下:

  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/cle.pdb" /debug /machine:I386 /out:"Debug/cle.exe" /pdbtype:sept 把它修改成:

  Link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/cle.pdb" /debug /machine:I386 /out:"Debug/cle.exe" /pdbtype:sept Debug/t1.obj Debug/t2.obj Debug/main.obj

  pause

  注意前面多了Link.exe,后面多了Debug/t1.obj Debug/t2.obj Debug/main.obj以及

  最后一个pause批处理命令,然后把它另存到工程目录(此目录下会看到debug目录)下起名为link.bat

  运行它,就会看到:

  t2.obj : error LNK2005: "void __cdecl Foo(void)" (?Foo@@YAXXZ) already defined in t1.obj

  Debug/cle.exe : fatal error LNK1169: one or more multiply defined symbols found

  很好,我们链接原来的obj文件得到的效果跟在vc中用rebuild all出来的效果一样。那么现在如果

  我们把备份出来的t1.obj_inline覆盖t1.obj而t2.obj_inline覆盖t2.obj再手动链接应该会是

  不会出错的,因为原t1.obj_inline及t2.obj_inline中存放的是内部链接符号。好运行Link.bat,果然

  不出所料,链接成功了,看看debug目录下多出了一个exe文件。这就说明了内或外符号在obj有标志标识!

  (提示:上述为什么不用vc的f7build链接呢,因为文件时间改变了,build会重新生成新的obj,

  所以我们用手动链接保证obj不变)[注bj信息可用dumpbin.exe查看]

  4.#i nclude规则:

  有很多人不知道#i nclude 文件该放在何处?

  1). 增强部件自身的完整性:

  为了保证部件完整,部件的cpp实现文件(如test.cpp)中第一个#i nclude的应当是它自身对应的头文件(如test.h)。

  (除非你用预编译头文件, 预编译头必须放在第一个)。这样就保证了该部件头文件(test.h)所必须依赖的其它接口(如a.h等)要放到它对应的文件头中(test.h),而不是在cpp中(test.cpp)把所依赖的其它头文件(a.h等)移到其自身对应的头文件(test.h等)之前(因为这样强迫其它包括此部件的头文件(test.h)的文件(b.cpp)也必须再写一遍include(即b.cpp若要#i nclude "test.h"也必须#i nclude "a.h")”。另外我们一般会尽量减少文件头之间的依赖关系,看下面:

  2). 减少部件之间的依赖性:

  在1的基础上尽量把#i nclude到的文件放在cpp中包括。

  这就要求我们一般不要在头文件中直接引用其它变量的实现,而是把此引用搬到实现文件中。

  例如:

  ...........

  };

  // 文件test.cpp:

  #i nclude "test.h"

  .....

  如上文件test.h中我们其实可以#i nclude "foo.h"移到test.cpp文件中。因为CFoo* m_pFoo我们只想在部件CTest中用到,而将来想用到CTest部件而包括test.h的其它部件没有必要见到foo.h接口,所以我们用前向声明修改原文件如下:

  // 文件foo.h:

  class CFoo{

  public:

  void Foo(){}

  #i nclude "test.h" // 这里第一个放该部件自身对应的接口头文件

  #i nclude "foo.h" // 该部件用到了foo.h

  CTest::CTest() : m_pFoo(0){

  m_pFoo = new CFoo;

  }

  void CTest::Test(){

  if(m_pFoo){

  m_pFoo->Foo();

  }

  }

  //.....

  // 再加上main.cpp来测试:

  #i nclude "test.h" // 这里我们就不用见到#i nclude "foo.h"了

  CTest test;

  void main(){

  test.Test();

  }

  3). 双重包含卫哨:

  在文件头中包括其它头文件时(如:#i nclude "xx.h")建议也加上包含卫哨:

  // test.h文件内容:

  #ifndef __XX1_H_

  #i nclude "xx1.h"

  #endif

  #ifndef __XX2_H_

  #i nclude "xx2.h"

  #endif

  ......

  虽然我们已经在xx.h文件中开头已经加过,但是因为编译器在打开#i nclude文件也是需要时间的,如果在外部加上包含卫哨,对于很大的工程可以节省更多的编译时间。

  5.待续(还有很多相关的东东,比如不同dll工程之间符号导出问题等等,有空再写)

  转自

  ------------------------------------------------

  最近我抽空研究、整理了一下VC中几个以前比较模糊的问题,写成这篇短文,希望和碰到过类似问题的朋友共享。 如果我的理解有不正确的地方,欢迎大家指正。

 

文章的3、4小节参照了vcforever的专栏(http://blog.csdn.net/vcforever/archive/2004/12/14/ 215936.aspx)。其它信息来源于MSDN和自己的摸索。

  1、Run-Time Library

  Run-Time Library是编译器提供的标准库,提供一些基本的库函数和系统调用。

  我们一般使用的Run-Time Library是C Run-Time Libraries。当然也有Standard C++ libraries。

  C Run-Time Libraries实现ANSI C的标准库。VC安装目录的CRT目录有C Run-Time库的大部分源代码。

  C Run-Time Libraries有静态库版本,也有动态链接库版本;有单线程版本,也有多线程版本;还有调试和非调试版本。

  可以在"project"-"settings"-"C/C++"-"Code Generation"中选择Run-Time Library的版本。

  动态链接库版本:

  /MD Multithreaded DLL 使用导入库MSVCRT.LIB

  /MDd Debug Multithreaded DLL 使用导入库MSVCRTD.LIB

  静态库版本:

  /ML Single-Threaded 使用静态库LIBC.LIB

  /MLd Debug Single-Threaded 使用静态库LIBCD.LIB

  /MT Multithreaded 使用静态库LIBCMT.LIB

  /MTd Debug Multithreaded 使用静态库LIBCMTD.LIB

  C Run-Time Library的标准io部分与操作系统的关系很密切,在Windows上,CRT的io部分代码只是一个包装,底层要用到操作系统内核kernel32.dll中的函数,在编译时使用导入库kernel32.lib。这也就是为什么在嵌入式环境中,我们一般不能直接使用C标准库。

  在Linux环境当然也有C标准库,例如:

  ld -o output /lib/crt0.o hello.o -lc

  参数"-lc"就是在引用C标准库libc.a。猜一猜"-lm"引用哪个库文件?

  2、常见的编译参数

  VC建立项目时总会定义"Win32"。控制台程序会定义"_CONSOLE",否则会定义"_WINDOWS"。Debug版定义"_DEBUG",Release版定义"NDEBUG" 。

  与MFC DLL有关的编译常数包括:

  _WINDLL 表示要做一个用到MFC的DLL

  _USRDLL 表示做一个用户DLL(相对MFC扩展DLL而言)

  _AFXDLL 表示使用MFC动态链接库

  _AFXEXT 表示要做一个MFC扩展DLL

  所以:

  Regular, statically linked to MFC _WINDLL,_USRDLL

  Regular, using the shared MFC DLL _WINDLL,_USRDLL,_AFXDLL

  Extension DLL _WINDLL,_AFXDLL,_AFXEXT

  CL.EXE编译所有源文件,LINK.EXE链接EXE和DLL,LIB.EXE产生静态库。

  3、subsystem和可执行文件的启动

  LINK的时候需要指定/subsystem,这个链接选项告诉Windows如何运行可执行文件。

  控制台程序是/subsystem:"console"

  其它程序一般都是/subsystem:"windows "

  将 subsystem 选成"console"后,Windows在进入可执行文件的代码前(如mainCRTStartup),就会产生一个控制台窗口。 如果选择"windows",操作系统就不产生console窗口,该类型应用程序的窗口由用户自己创建。

  可执行文件都有一个Entry Point,LINK时可以用/entry指定。缺省情况下,如果subsystem是“console”,Entry Point是 mainCRTStartup(ANSI)或wmainCRTStartuup(UNICODE),即:

  /subsystem:"console" /entry:"mainCRTStartup" (ANSI)

  /subsystem:"console" /entry:"wmainCRTStartuup" (UNICODE)

  mainCRTStartup 或 wmainCRTStartuup 会调用main或wmain。

  值得一提的是,在进入应用程序的Entry Point前,Windows的装载器已经做过C变量的初始化,有初值的全局变量拥有了它们的初值,没有初值的变量被设为0。

  如果subsystem是“windows”,Entry Point是WinMain(ANSI)或wWinMain(UINCODE),即:

  /subsystem:"windows" /entry:"WinMainCRTStartup" (ANSI)

  /sbusystem:"windows" /entry:"wWinMainCRTStartup" (UINCODE)

  WinMainCRTStartup 或 wWinMainCRTStartup 会调用 WinMain 或 wWinMain。

  如果使用MFC框架,WinMain也会被埋藏在MFC库中(APPMODUL.CPP):

  extern "C" int WINAPI

  _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

  LPTSTR lpCmdLine, int nCmdShow)

  {

  // call shared/exported WinMain

  return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

  }

  "_t"是一个宏,对于ANSI版本,"_tWinMain"就是"WinMain";对于UINCODE版本,"_tWinMain"就是"wWinMain"。

  全局C++对象的构造函数是在什么地方调用的?答案是在进入应用程序的Entry Point后,在调用main函数前的初始化操作中。所以MFC的theApp的构造函数是在_tWinMain之前调用的。

  4、不显示Console窗口的Console程序

  在默认情况下/subsystem 和/entry开关是匹配的,也就是:

  "console"对应"mainCRTStartup"或者"wmainCRTStartup"

  "windows"对应"WinMain"或者"wWinMain"

  我们可以通过手动修改的方法使他们不匹配。例如:

  #i nclude "windows.h"

  #pragma comment( linker, "/subsystem:/"windows/" /entry:/"mainCRTStartup/"" ) // 设置入口地址

  void main(void)

  {

  MessageBox(NULL, "hello", "Notice", MB_OK);

  }

  这个Console程序就不会显示Console窗口。如果选/MLd的话,这个程序只需要链接LIBCD.LIB user32.lib kernel32.lib。

  5、VC中缺省库冲突的解决

  VC的编译器在编译程序时有两个习惯:

  a、在从头开始编译时,将源文件名按字母排序后,依次处理;

  b、一边编译一边决定需要哪些缺省库。

  它的这些习惯有时会造成奇怪的编译错误,例如项目中有两个文件:

  charutil.c

  gbnni.cpp

  其中gbnni.cpp用到了MFC库。

  它老兄当然是先处理charutil.c,然后觉得需要link一个C Runtime库,根据项目设置选择了LIBCMTD.lib。

  然后又处理gbnni.cpp,因为要用MFC,又决定要link nafxcwd.lib。

  最后link的时候,就会出现以下冲突:

  nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)

  其实,如果先link了nafxcwd.lib,就没有必要再link LIBCMTD.lib,也就不会产生冲突。

  解决这类问题有两个办法。

  a、让项目的第一个文件包含MFC的头文件,这样编译器就不会想到找C Runtime库。这样就要把c文件改成cpp了。

  b、将需要link C Runtime库的文件的名字改大一些,让它排在后面。

  使用IDE当然很方便,但既然使用了别人写的工具,有时就不得不琢磨、迁就它的习性。 上面有一处笔误,如果subsystem是“windows”,Entry Point应该是WinMainCRTStartup(ANSI)或wWinMainCRTStartup(UINCODE。

  探讨这些问题的动机是想弄清楚我们的程序是如何装载、运行的。但是,由于Windows不是开源平台,我也只能查到PE文件(Windows上可执行文件的格式)。entry point、subsystem都是PE文件头的一部分。

  Windows在进入PE文件的entry point之前做了些什么,就看不到了,只能大概推测:应该是创建一个进程,装载PE文件和所有需要的DLL,初始化C变量,然后从某个起点函数开始运行。不同的subsystem,应该有不同的起点。调用这个起点函数时应该传入PE文件的entry point地址。

  转自http://topic.csdn.net/t/20050428/22/3974737.html

  zz 关于LNK2005错误--

  编程中经常能遇到LNK2005错误——重复定义错误,其实LNK2005错误并不是一个很难解决的错误。弄清楚它形成的原因,就可以轻松解决它了。

  造成LNK2005错误主要有以下几种情况:

  1.重复定义全局变量。可能存在两种情况:

  A、对于一些初学编程的程序员,有时候会以为需要使用全局变量的地方就可以使用定义申明一下。其实这是错误的,全局变量是针对整个工程的。正确的应该是在一个CPP文件中定义如下:int g_Test;那么在使用的CPP文件中就应该使用:extern int g_Test即可,如果还是使用int g_Test,那么就会产生LNK2005错误,一般错误错误信息类似:AAA.obj error LNK2005 int book c?book@@3HA already defined in BBB.obj。切记的就是不能给变量赋值否则还是会有LNK2005错误。

  这里需要的是“声明”,不是“定义”!根据C++标准的规定,一个变量是声明,必须同时满足两个条件,否则就是定义:

  (1)声明必须使用extern关键字;(2)不能给变量赋初值

  所以,下面的是声明:

  extern int a;

  下面的是定义

  int a; int a = 0; extern int a =0;

  B、对于那么编程不是那么严谨的程序员,总是在需要使用变量的文件中随意定义一个全局变量,并且对于变量名也不予考虑,这也往往容易造成变量名重复,而造成LNK2005错误。

  2.头文件的包含重复。往往需要包含的头文件中含有变量、函数、类的定义,在其它使用的地方又不得不多次包含之,如果头文件中没有相关的宏等防止重复链接的措施,那么就会产生LNK2005错误。解决办法是在需要包含的头文件中做类似的处理:#ifndef MY_H_FILE //如果没有定义这个宏

  #define MY_H_FILE //定义这个宏

  ……. //头文件主体内容

  …….

  #endif

  上面是使用宏来做的,也可以使用预编译来做,在头文件中加入:

  #pragma once

  //头文件主体

  3.使用第三方的库造成的。这种情况主要是C运行期函数库和MFC的库冲突造成的。具体的办法就是将那个提示出错的库放到另外一个库的前面。另外选择不同的C函数库,可能会引起这个错误。微软和C有两种C运行期函数库,一种是普通的函数库:LIBC.LIB,不支持多线程。另外一种是支持多线程的:msvcrt.lib。如果一个工程里,这两种函数库混合使用,可能会引起这个错误,一般情况下它需要MFC的库先于C运行期函数库被链接,因此建议使用支持多线程的msvcrt.lib。所以在使用第三方的库之前首先要知道它链接的是什么库,否则就可能造成LNK2005错误。如果不得不使用第三方的库,可以尝试按下面所说的方法修改,但不能保证一定能解决问题,前两种方法是微软提供的:

  A、选择VC菜单Project->Settings->Link->Catagory选择Input,再在Ignore libraries 的Edit栏中填入你需要忽略的库,如:Nafxcwd.lib;Libcmtd.lib。然后在Object/library Modules的Edit栏中填入正确的库的顺序,这里需要你能确定什么是正确的顺序,呵呵,God bless you!

  B、选择VC菜单Project->Settings->Link页,然后在Project Options的Edit栏中输入/verbose:lib,这样就可以在编译链接程序过程中在输出窗口看到链接的顺序了。

  C、选择VC菜单Project->Settings->C/C++页,Catagory选择Code Generation后再在User Runtime libraray中选择MultiThread DLL等其他库,逐一尝试。

这篇关于编译全攻略-编译器处理及LNK错误的解决方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/481790

相关文章

检查 Nginx 是否启动的几种方法

《检查Nginx是否启动的几种方法》本文主要介绍了检查Nginx是否启动的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1. 使用 systemctl 命令(推荐)2. 使用 service 命令3. 检查进程是否存在4

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

Java方法重载与重写之同名方法的双面魔法(最新整理)

《Java方法重载与重写之同名方法的双面魔法(最新整理)》文章介绍了Java中的方法重载Overloading和方法重写Overriding的区别联系,方法重载是指在同一个类中,允许存在多个方法名相同... 目录Java方法重载与重写:同名方法的双面魔法方法重载(Overloading):同门师兄弟的不同绝

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

springboot中配置logback-spring.xml的方法

《springboot中配置logback-spring.xml的方法》文章介绍了如何在SpringBoot项目中配置logback-spring.xml文件来进行日志管理,包括如何定义日志输出方式、... 目录一、在src/main/resources目录下,也就是在classpath路径下创建logba

解决idea启动项目报错java: OutOfMemoryError: insufficient memory

《解决idea启动项目报错java:OutOfMemoryError:insufficientmemory》:本文主要介绍解决idea启动项目报错java:OutOfMemoryError... 目录原因:解决:总结 原因:在Java中遇到OutOfMemoryError: insufficient me

SQL Server中行转列方法详细讲解

《SQLServer中行转列方法详细讲解》SQL行转列、列转行可以帮助我们更方便地处理数据,生成需要的报表和结果集,:本文主要介绍SQLServer中行转列方法的相关资料,需要的朋友可以参考下... 目录前言一、为什么需要行转列二、行转列的基本概念三、使用PIVOT运算符进行行转列1.创建示例数据表并插入数