调试SQLSERVER (二)使用Windbg调试SQLSERVER的环境设置 调试SQLSERVER (一)生成dump文件的方法 调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令 大家知道在Windows里面,调试可以分为两个领域: 1、内核态调试 2、用户态调试 一般的程序都是运行
调试SQLSERVER (二)使用Windbg调试SQLSERVER的环境设置
调试SQLSERVER (一)生成dump文件的方法
调试SQLSERVER (三)使用Windbg调试SQLSERVER的一些命令
大家知道在Windows里面,调试可以分为两个领域:
1、内核态调试
2、用户态调试
一般的程序都是运行在用户态,包括SQLSERVER,SQLServer 会依赖于操作系统的Win32/Win64 API去调用I/O或者其他他需要的服务
用户态程序调试和内核态程序调试是不太一样的,即使有些命令是一样的
还有另外一个要注意的是 live debug和dump file
live debug:直接附加调试器到进程--使进程hang住,使被调试程序不能继续执行代码
dump file :通常是一个dump文件,dump文件是进程生成的当时这个进程的所有或部分内存内容,并且可以被调试器读取
full dump文件 通常的扩展名是.dmp ,文件里面一般不包含已经paged out 的内存内容
mini dump文件 通常的扩展名是.mdmp ,一般只包含线程栈和加载的模块名
Windbg: 是一个GUI调试器工具并且可以调试内核态和用户态程序,除了Windbg调试器 当然还有其他调试器 ,例如kd, cdb, ntsd
简单复习
应用程序以进程运行,这里我们关注的进程是sqlservr.exe ,在用户态调试下,我们会调试一个单独的进程,无论是使用live debug(附加进程方式)还是读取一个dump文件
在调试的时候都能看到进程的内存空间。在内核态调试里,我们可以看到所有进程和他们的内存空间(注意:在dump文件里面我们访问不到当生成dump文件的时候
已经被paged out 的那部分内存地址)
stack trace:单个线程里面执行的代码的栈,一个线程可以有用户态栈和内核态栈,在用户态调试里面,我们只能看到每个线程的用户态栈
一个stack trace是一个线程的一系列函数调用的list
stack是一个LIFO结构(last in first out)意思是后进先出,术语叫做push stack 和pop stack
栈的读取是自底向上的,最上面的调用是当前正在执行的代码
下面的例子
Child SP (Stack Pointer)
RetAddr (Return Address)
stack trace里面可以跟踪系统的执行顺序和调用代码的返回,调试器会构造stack trace 给我们以便于更好的分析
Child<span>-</span><span>SP RetAddr Call Site </span><span>00000000</span>`09cbe9e8 <span>00000000</span>`777b2f60 ntdll!NtSignalAndWaitForSingleObject<span>+</span><span>0xa</span> <span>00000000</span>`09cbe9f0 <span>00000000</span>`00bdc99e kernel32!SignalObjectAndWait<span>+</span><span>0x110</span> <span>00000000</span>`09cbeaa0 <span>00000000</span>`00bc4575 sqlservr<span>+</span><span>0x1c99e</span> <span>00000000</span>`09cbed40 <span>00000000</span>`00bc3ea8 sqlservr<span>+</span><span>0x4575</span> <span>00000000</span>`09cbed80 <span>00000000</span>`00bdcfad sqlservr<span>+</span><span>0x3ea8</span> <span>00000000</span>`09cbf370 <span>00000000</span>`01139d9c sqlservr<span>+</span><span>0x1cfad</span> <span>00000000</span>`09cbf430 <span>00000000</span>`032b34c7 sqlservr<span>+</span><span>0x579d9c</span> <span>00000000</span>`09cbf650 <span>00000000</span>`00bd2abb sqlservr!TlsGetValueForMsxmlSQL<span>+</span><span>0x4706d7</span> <span>00000000</span>`09cbf6c0 <span>00000000</span>`00bd0fda sqlservr<span>+</span><span>0x12abb</span> <span>00000000</span>`09cbf7e0 <span>00000000</span>`00bd2665 sqlservr<span>+</span><span>0x10fda</span> <span>00000000</span>`09cbf870 <span>00000000</span>`0117abb0 sqlservr<span>+</span><span>0x12665</span> <span>00000000</span>`09cbf8e0 <span>00000000</span>`0117c4b0 sqlservr<span>+</span><span>0x5babb0</span> <span>00000000</span>`09cbf9a0 <span>00000000</span>`0117a060 sqlservr<span>+</span><span>0x5bc4b0</span> <span>00000000</span>`09cbf9d0 <span>00000000</span>`0117a9ef sqlservr<span>+</span><span>0x5ba060</span> <span>00000000</span>`09cbfa60 <span>00000000</span>`734937d7 sqlservr<span>+</span><span>0x5ba9ef</span> <span>00000000</span>`09cbfaf0 <span>00000000</span>`<span>73493894</span> MSVCR80!endthreadex<span>+</span><span>0x47</span> <span>00000000</span>`09cbfb20 <span>00000000</span>`7775f56d MSVCR80!endthreadex<span>+</span><span>0x104</span> <span>00000000</span>`09cbfb50 <span>00000000</span>`<span>77893281</span> kernel32!BaseThreadInitThunk<span>+</span><span>0xd</span> <span>00000000</span>`09cbfb80 <span>00000000</span>`<span>00000000</span> ntdll!RtlUserThreadStart<span>+</span><span>0x21</span>
在配置调试器的过程中,最后的步骤是匹配符号,我们打开Windbg的时候我们必须设置我们的符号文件路径
Symbolic Debugging Files(符号调试文件):帮助调试器把内存里面的各自的函数,类,变量名在内存的位置 匹配到相应的内存地址和位移
如果没有Symbolic Debugging Files,那么我们将会看到下面只有memory addresses 的stack trace
符号文件的扩展名通常是pdb(如果大家写C#代码的时候肯定都会看到过在debug的时候看到bin目录下会有debug符号文件),调试器能够很好地解析这种文件格式
Child<span>-</span><span>SP RetAddr Call Site </span><span>00000000</span>`09cbe9e8 <span>00000000</span>`777b2f60 ntdll!NtSignalAndWaitForSingleObject<span>+</span><span>0xa</span> <span>00000000</span>`09cbe9f0 <span>00000000</span>`00bdc99e kernel32!SignalObjectAndWait<span>+</span><span>0x110</span> <span>00000000</span>`09cbeaa0 <span>00000000</span>`00bc4575 sqlservr<span>+</span><span>0x1c99e</span> <span>00000000</span>`09cbed40 <span>00000000</span>`00bc3ea8 sqlservr<span>+</span><span>0x4575</span> <span>00000000</span>`09cbed80 <span>00000000</span>`00bdcfad sqlservr<span>+</span><span>0x3ea8</span> <span>00000000</span>`09cbf370 <span>00000000</span>`01139d9c sqlservr<span>+</span><span>0x1cfad</span> <span>00000000</span>`09cbf430 <span>00000000</span>`032b34c7 sqlservr<span>+</span><span>0x579d9c</span> <span>00000000</span>`09cbf650 <span>00000000</span>`00bd2abb sqlservr!TlsGetValueForMsxmlSQL<span>+</span><span>0x4706d7</span> <span>00000000</span>`09cbf6c0 <span>00000000</span>`00bd0fda sqlservr<span>+</span><span>0x12abb</span> <span>00000000</span>`09cbf7e0 <span>00000000</span>`00bd2665 sqlservr<span>+</span><span>0x10fda</span> <span>00000000</span>`09cbf870 <span>00000000</span>`0117abb0 sqlservr<span>+</span><span>0x12665</span> <span>00000000</span>`09cbf8e0 <span>00000000</span>`0117c4b0 sqlservr<span>+</span><span>0x5babb0</span> <span>00000000</span>`09cbf9a0 <span>00000000</span>`0117a060 sqlservr<span>+</span><span>0x5bc4b0</span> <span>00000000</span>`09cbf9d0 <span>00000000</span>`0117a9ef sqlservr<span>+</span><span>0x5ba060</span> <span>00000000</span>`09cbfa60 <span>00000000</span>`734937d7 sqlservr<span>+</span><span>0x5ba9ef</span> <span>00000000</span>`09cbfaf0 <span>00000000</span>`<span>73493894</span> MSVCR80!endthreadex<span>+</span><span>0x47</span> <span>00000000</span>`09cbfb20 <span>00000000</span>`7775f56d MSVCR80!endthreadex<span>+</span><span>0x104</span> <span>00000000</span>`09cbfb50 <span>00000000</span>`<span>77893281</span> kernel32!BaseThreadInitThunk<span>+</span><span>0xd</span> <span>00000000</span>`09cbfb80 <span>00000000</span>`<span>00000000</span> ntdll!RtlUserThreadStart<span>+</span><span>0x21</span>
上面显示出我们的模块,sqlservr.exe 和正在执行的代码在地址空间里的位移,但是我们不知道具体的函数名,如果有符号映射的帮助(symbols mapped),我们可以获取到更有意义输出
Child<span>-</span><span>SP RetAddr Call Site </span><span>00000000</span>`09cbe9e8 <span>00000000</span>`777b2f60 ntdll!NtSignalAndWaitForSingleObject<span>+</span><span>0xa</span> <span>00000000</span>`09cbe9f0 <span>00000000</span>`00bdc99e kernel32!SignalObjectAndWait<span>+</span><span>0x110</span> <span>00000000</span>`09cbeaa0 <span>00000000</span>`00bc4575 sqlservr!SOS_Scheduler::SwitchContext<span>+</span><span>0x84e</span> <span>00000000</span>`09cbed40 <span>00000000</span>`00bc3ea8 sqlservr!SOS_Scheduler::SuspendNonPreemptive<span>+</span><span>0xc5</span> <span>00000000</span>`09cbed80 <span>00000000</span>`00bdcfad sqlservr!EventInternal<span>Spinlock<span><span>149</span>,<span>1</span>,<span>0</span><span>></span> <span>></span>::Wait<span>+</span><span>0x428</span> <span>00000000</span>`09cbf370 <span>00000000</span>`01139d9c sqlservr!ResQueueBase::Dequeue<span>+</span><span>0x19d</span> <span>00000000</span>`09cbf430 <span>00000000</span>`032b34c7 sqlservr!CheckpointLoop<span>+</span><span>0x1aa</span> <span>00000000</span>`09cbf650 <span>00000000</span>`00bd2abb sqlservr!ckptproc<span>+</span><span>0x47</span> <span>00000000</span>`09cbf6c0 <span>00000000</span>`00bd0fda sqlservr!SOS_Task::Param::<span>Execute</span><span>+</span><span>0x11b</span> <span>00000000</span>`09cbf7e0 <span>00000000</span>`00bd2665 sqlservr!SOS_Scheduler::RunTask<span>+</span><span>0xca</span> <span>00000000</span>`09cbf870 <span>00000000</span>`0117abb0 sqlservr!SOS_Scheduler::ProcessTasks<span>+</span><span>0x95</span> <span>00000000</span>`09cbf8e0 <span>00000000</span>`0117c4b0 sqlservr!SchedulerManager::WorkerEntryPoint<span>+</span><span>0x110</span> <span>00000000</span>`09cbf9a0 <span>00000000</span>`0117a060 sqlservr!SystemThread::RunWorker<span>+</span><span>0x60</span> <span>00000000</span>`09cbf9d0 <span>00000000</span>`0117a9ef sqlservr!SystemThreadDispatcher::ProcessWorker<span>+</span><span>0x12c</span> <span>00000000</span>`09cbfa60 <span>00000000</span>`734937d7 sqlservr!SchedulerManager::ThreadEntryPoint<span>+</span><span>0x12f</span> <span>00000000</span>`09cbfaf0 <span>00000000</span>`<span>73493894</span> MSVCR80!endthreadex<span>+</span><span>0x47</span> <span>00000000</span>`09cbfb20 <span>00000000</span>`7775f56d MSVCR80!endthreadex<span>+</span><span>0x104</span> <span>00000000</span>`09cbfb50 <span>00000000</span>`<span>77893281</span> kernel32!BaseThreadInitThunk<span>+</span><span>0xd</span> <span>00000000</span>`09cbfb80 <span>00000000</span>`<span>00000000</span> ntdll!RtlUserThreadStart<span>+</span><span>0x21</span></span></span>
从上面的输出的函数名我们可以看到Checkpoint 线程
上面看到worker thread在CHECKPOINT_QUEUE 队列里面等待CHECKPOINT 命令
大家可以看到加上符号文件之后,调试器会在stack trace相应的位置进行转换,例如在模块名那里加上模块名,在函数名那里加上函数名
<span>module_name<span>>!<span>function</span> call<span>></span> <span>or</span> <span>module_name<span>>!class_name<span>></span>::<span>method<span>/</span><span>function</span> call<span>></span></span></span></span></span></span>
设置符号路径
设置符号路径的作用是使调试器可以找到符号文件的位置并进行加载在调试的时候
简单介绍一下符号路径和公私有符号文件
私有符号文件:包含了调试会话中需要的所有符号信息(只对微软内部开放,微软私有财产)
公有符号文件:只是有选择地包含一些符号信息(对所有人开放)
符号信息隶属于指定的模块,只有调试器需要用到某个模块时,它的符号信息才有被加载和分析的必要。
要在调试器中使用符号,我们必须首先告诉调试器这些符号文件的位置,也就是设置符号路径。符号路径可以是本地文件夹路径、可访问的UNC路径、或者是符号服务器路径。
符号服务器:在调试过程中,需要涉及成千上万个符号文件,以及同一个符号文件存在不同平台下的不同符号文件版本的时候。
手动设置符号路径肯定是不现实的,于是引入了符号服务器的概念。
符号服务器有一套命名规则,使得调试软件能够正确找到需要的符号文件。一般来说,符号服务器比较大,都是共用的,放在远程主机上。
为了降低网络访问的成本,又引入了符号缓存的概念,即将从服务器上下载到的符号文件,保存在本地缓存中,以后调试器需要符号文件的时候,先从缓存中寻找,找不到的时候再到服务器上下载。
1、设置符号路径
设置符号路径的语法如下:
.sympath [+] [路径]
如要覆盖原来的路径设置,使用新路径即可:
.sympath
要在原有路径的基础上添加一个新路径,可使用:
.sympath+
如果不带参数,那么输出是当前设置的符号路径:
0:000> .sympath Symbol search path is: <empty> //尚未设置符号路径</empty>
假如在调试时,我知道需要的符号文件位于一下文件夹"D:\MyPdb“。
0:000> .sympath D:\MyPdb //覆盖原有符号路径 Symbol search path is: D:\MyPdb Expanded Symbol search path is: d:\mypdb
此时调试器将记录上面新的符号路径,但并不会从这个路径中加载任何符号,要指示调试器加载符号,可以使用元命令reload。
这个命令能枚举出进程地址空间中所有已加载的模块,并且尝试找出与各个模块相关的符号文件。
0:000> .reload Reloading current modules .....
如果调试器在指定目录无法找到文件,那么它会输出错误提示:
*** ERROR:Symbol file could not be found. Defaulted to export symbols for xxx.dll
当没有设置本地缓存路径时,那么调试器将使用调试软件的安装路径下的sym文件夹。
要特别注意的是,使用.sympath改变或新增符号路径后,符号文件并不会自动更新,应再执行.reload命令以进行更新。
2、符号服务器与符号缓存
设置符号服务器的基本语法是:
SRV*[符号缓存]*服务器地址
语法有SRV引导,符号缓存和服务器地址的前面各有一个星号引导。
此外,我们总是应该把微软的公用符号库加入到我们的符号路径中:
.sympath+ srv**http://msdl.microsoft.com/download/symbols
这是一台微软对外公开的服务器,使用http地址访问,不是所有人都能牢记这个网址,所以最好的办法就是使用.symfix命令(自动记忆了上面那个微软符号服务器地址),语法如下:
.symfix [+] [符号缓存地址]
下面的命令等价于上面的.sympath命令,而不用输入长长的http地址。
0:010> .symfix c:\windows\symbols 0:010> .sympath Symbol search path is: srv* Expanded Symbol search path is: SRV*c:\windows\symbols*http://msdl.microsoft.com/download/symbols
以上设置后,当需要用到符号,Windbg将自动到服务器上去下载,然后保存在C:\windows\symbols
当然,我们也可以在计算机上面设置,设置方式是:
我的电脑=》高级系统设置=》高级Tab,点击环境变量,新建一个用户变量如
变量名:_NT_SYMBOL_PATH
变量值:SRV*D:\PDB*http://msdl.microsoft.com/download/symbols/
或者
在安装完符号文件之后,指定固定的路径
变量名:_NT_SYMBOL_PATH
变量值:C:\windows\symbols
2、重新加载
如果对自己正在使用的符号文件感到疑惑,比如源代码和行号明显不匹配,最好就是重新加载一下符号文件。此命令语法如下:
.reload /f /v [模块名]
.reload命令的作用是删除指定或所有已加载的符号文件,默认情况下,调试器不会立刻根据符号路径重新搜索并加载新的符号文件,而是推迟到调试器下一次使用此文件时。
使用/f参数将破事调试器立刻搜索并重新加载新的符号文件。
其它参数解释如下:
/v:将搜索过程中的详细信息都显示出来。
/i:不检查pdb文件的版本信息;
/l:只显示模块信息,内核模式下,和“lm n t”命令类似,但显示内容比后者更多,因为包含了用户模块信息;
/n:仅重载内核符号,不重载用户符号;
/o:强制覆盖符号库中的符号文件,即使版本相同;
/d:用户层模式下使用Windbg时的默认选项,重载调试器模块列表中的所有模块;
/s:内核模式下使用Windbg时的默认选项,重载系统模块列表中的所有模块,另外,如果调试器在用户模式下运行,要加载内核模块,也必须使用/s选项,否则调试器将只会在调试器模块列表中搜索而导致找不到内核模块;
/u:卸载指定模块。如发现当前符号版本不对,使用/u开关先卸载之再重新加载。
下面命令重新加载sqlservr模块
.reload <span>/</span>f sqlservr.exe
上面讲了一大堆,什么符号服务器,什么符号缓存,但是我们一般只使用本地符号文件,实际上概括起来我们设置符号路径一般的做法就是
1、下载公有符号文件,并安装,然后设置
地址:http://msdn.microsoft.com/zh-cn/windows/hardware/gg463028
双击下载下来的安装包,然后安装
下面这个路径一定要记住!!
安装完毕之后就可以在E:\Symbols\路径下 看到安装好的pdb
pdb文件
2、在Windbg里面设置symbols文件夹的位置
我们随便加载一个mdmp文件
打开dump文件之后,在Windbg的命令框依次输入下面命令
.sympath E:\Symbols
重新加载
.reload
然后再输入 .sympath 就会看到当前符号路径是E:\Symbols
当然,我们不可能每次调试dump文件的时候都指定一次符号路径,我们可以把符号路径添加到环境变量里
这样下次再打开Windbg的时候就不用再指定多一次符号路径
我们再次打开Windbg,可以发现Windbg会首先从环境变量里查找符号路径,下图看到Windbg已经查找成功
这样就省去了我们每次设置符号路径的麻烦
总结
这样我们的调试环境就弄好了,下篇会介绍Windbg的一些命令
参考文章:
http://blogs.msdn.com/b/askjay/archive/2009/12/29/basic-debugging-concepts-and-setup.aspx
关于符号路径,符号服务器,符号文件的更多内容请参考:Windbg符号与源码 《第二篇》
欢迎大家拍砖o(∩_∩)o

산성 속성에는 원자력, 일관성, 분리 및 내구성이 포함되며 데이터베이스 설계의 초석입니다. 1. 원자력은 거래가 완전히 성공적이거나 완전히 실패하도록합니다. 2. 일관성은 거래 전후에 데이터베이스가 일관성을 유지하도록합니다. 3. 격리는 거래가 서로를 방해하지 않도록합니다. 4. 지속성은 거래 제출 후 데이터가 영구적으로 저장되도록합니다.

MySQL은 데이터베이스 관리 시스템 (DBMS) 일뿐 만 아니라 프로그래밍 언어와 밀접한 관련이 있습니다. 1) DBMS로서 MySQL은 데이터를 저장, 구성 및 검색하는 데 사용되며 인덱스 최적화는 쿼리 성능을 향상시킬 수 있습니다. 2) SQL과 같은 ORM 도구를 사용하여 Python에 내장 된 SQL과 프로그래밍 언어를 결합하면 작업을 단순화 할 수 있습니다. 3) 성능 최적화에는 인덱싱, 쿼리, 캐싱, 라이브러리 및 테이블 부서 및 거래 관리가 포함됩니다.

MySQL은 SQL 명령을 사용하여 데이터를 관리합니다. 1. 기본 명령에는 선택, 삽입, 업데이트 및 삭제가 포함됩니다. 2. 고급 사용에는 조인, 하위 쿼리 및 집계 함수가 포함됩니다. 3. 일반적인 오류에는 구문, 논리 및 성능 문제가 포함됩니다. 4. 최적화 팁에는 인덱스 사용, 선택*을 피하고 한계 사용이 포함됩니다.

MySQL은 데이터 저장 및 관리에 적합한 효율적인 관계형 데이터베이스 관리 시스템입니다. 장점에는 고성능 쿼리, 유연한 트랜잭션 처리 및 풍부한 데이터 유형이 포함됩니다. 실제 애플리케이션에서 MySQL은 종종 전자 상거래 플랫폼, 소셜 네트워크 및 컨텐츠 관리 시스템에서 사용되지만 성능 최적화, 데이터 보안 및 확장성에주의를 기울여야합니다.

SQL과 MySQL의 관계는 표준 언어와 특정 구현의 관계입니다. 1.SQL은 관계형 데이터베이스를 관리하고 운영하는 데 사용되는 표준 언어로, 데이터 추가, 삭제, 수정 및 쿼리를 허용합니다. 2.MySQL은 SQL을 운영 언어로 사용하고 효율적인 데이터 저장 및 관리를 제공하는 특정 데이터베이스 관리 시스템입니다.

InnoDB는 Redologs 및 Undologs를 사용하여 데이터 일관성과 신뢰성을 보장합니다. 1. Redologs는 사고 복구 및 거래 지속성을 보장하기 위해 데이터 페이지 수정을 기록합니다. 2. 결점은 원래 데이터 값을 기록하고 트랜잭션 롤백 및 MVCC를 지원합니다.

설명 명령에 대한 주요 메트릭에는 유형, 키, 행 및 추가가 포함됩니다. 1) 유형은 쿼리의 액세스 유형을 반영합니다. 값이 높을수록 Const와 같은 효율이 높아집니다. 2) 키는 사용 된 인덱스를 표시하고 NULL은 인덱스가 없음을 나타냅니다. 3) 행은 스캔 한 행의 수를 추정하여 쿼리 성능에 영향을 미칩니다. 4) Extra는 최적화해야한다는 Filesort 프롬프트 사용과 같은 추가 정보를 제공합니다.

Temporary를 사용하면 MySQL 쿼리에 임시 테이블을 생성해야 할 필요성이 있으며, 이는 별개의, 그룹 비 또는 비 인덱스 열을 사용하여 순서대로 발견됩니다. 인덱스 발생을 피하고 쿼리를 다시 작성하고 쿼리 성능을 향상시킬 수 있습니다. 구체적으로, 설명 출력에 사용되는 경우, MySQL은 쿼리를 처리하기 위해 임시 테이블을 만들어야 함을 의미합니다. 이것은 일반적으로 다음과 같은 경우에 발생합니다. 1) 별개 또는 그룹을 사용할 때 중복 제거 또는 그룹화; 2) OrderBy가 비 인덱스 열이 포함되어있을 때 정렬하십시오. 3) 복잡한 하위 쿼리 또는 조인 작업을 사용하십시오. 최적화 방법은 다음과 같습니다. 1) Orderby 및 GroupB


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

Eclipse용 SAP NetWeaver 서버 어댑터
Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

WebStorm Mac 버전
유용한 JavaScript 개발 도구

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기
